0% found this document useful (0 votes)
11 views

Chapter I-CV

Uploaded by

jerald2016123
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

Chapter I-CV

Uploaded by

jerald2016123
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 341

1

Chapter 1

THE PROBLEM AND IT’S SETTING

1.1 Introduction

Every day, small and large businesses deal with many types of records and manual

information dissemination. These records and information might be used for historical,

demographic, social, medical, or scientific study, as well as benchmarks to gauge the

organization's future operations and choices. The Philippine government is a strong supporter

of social welfare. Every day, the Municipal Social Welfare and Development (MSWD)

Jasaan, like any other agency, generates a large amount of documents. These large printed

papers are stacked and kept at the records office and relevant departments for safekeeping

and future reference. The Municipality of Social Welfare and Development (MSWD) Jasaan

compiles records and distributes information or announcements on a regular basis, however

their record system is outdated, making it difficult to retrieve and track records. Furthermore,

it is difficult for them to tell each member of the organization's latest information or

announcements. To address widespread and persistent poverty, the Municipal Department of

Social Welfare and Development (MSWD) in Jasaan wants to improve social service

delivery to the poor and strengthen the department's capabilities in social protection. MSWD

has urged for the quick extension and enhancement of basic social protection programs,

specifically for people with disabilities, single parents, older citizens, children in need of

social protection, teenagers in need of special protection, women in very tough situations,

family heads, and other needy persons.

With this, MSWD Jasaan embarked into record's digitization for its management to

ensure the preservation of permanent and valuable papers, secured and accessible for future
2

reference as required by the organization's different offices based on existing rules and

regulations in record management. A mobile application for users that will update the

announcements of the MSWD Jasaan, with the help of this system and mobile application,

records safekeeping and retrieval bring comfort for the records officer and a hassle-free

transaction for each member of the protection programs.

A Municipal Social Welfare and Development System with SMS Notifier is a software

program used to administer a local government unit's social welfare and development

services. The purpose of this system is to automate and streamline the procedures involved in

providing social welfare and development services to the inhabitants of a certain municipality

or city. The system includes an SMS notifier, which delivers automated notifications to

recipients of social welfare and development programs. The SMS notifier can be used to

notify recipients of impending activities, appointments, or events associated with the services

they are receiving. This functionality may also be used to remind recipients of upcoming

appointments, submission deadlines, and other key dates relating to the services they are

receiving. The Municipal Social Welfare and Development System with SMS Notifier may

also be used to track and manage social welfare and development service recipients. It can

maintain track of the services received by each recipient, as well as the status of their

applications and the status of their cases. This system may also create information on the

number of beneficiaries served, the types of services delivered, and the service success rate.

In conclusion, the Municipal Social Welfare and Development System with SMS Notifier is

an effective instrument for assisting local government units in providing improved social

welfare and development services to its residents. This system can assist in automating and

streamlining the procedures involved in providing social welfare and development services,
3

as well as providing beneficiaries with timely information about significant events and

deadlines.

1.2 Conceptual Framework

The researchers used the IPO (Input, Output, Process) model for their conceptual

framework. The IPO model represents a system in three stages: input, processing, and output.

Inputs are modeled as consumables and efforts that are introduced to a system at the beginning

stage of its lifecycle. Outputs are modeled as the results produced by the system.

Input Process Output


Knowledge Planning
Requirements  Creates a quality
● Process and assurance plan
Getting System Analysis
● Information about  Find possible and
MSWD Jasaan appropriate
solutions
Software
Requirements System Design

 Identification  Developing a
of the mechanism,
process flow and MSWD Jasaan
development
other
tools that will Management System
documentation
be involved in related on how the with SMS Notifier
the project system will work
( visual studio)
Development
Hardware  Coding/
Requirements Programming
Testing
 Android
 Test the web
Mobile
application and
Application
mobile application
 PC/Laptop
Implementation
 Initializing and
testing for errors
4

Figure 1. Conceptual Framework

The input-process-output model is used in the conceptual framework to depict the stages
of project development. This provides as a guide for carrying out the research. The researchers
utilized the project's development tools (Visual Studio) to create the MSWD Jasaan Management
System with SMS Notifier for further information and announcements.

Input

Knowledge Requirements - this is the process of learning about the MSWD Jasaan

Management System through SMS Notifier.

Software Requirements - It is a list of the development tools that will be used in the project.

Hardware Requirements - For system access, Android mobile apps and desktop or laptop PCs

are required.

Process

Planning - is used to define the criteria and processes that will ensure and verify that data meet

specific data-quality objectives throughout the Data Lifecycle

System Analysis - System analysis is conducted for the purpose of studying a system or its parts

in order to identify its objectives.

System Design - Developing a mechanism, process flow and other documentation related on

how the system will work.


5

Development – Coding/programming testing, testing of the web application, and testing of the

mobile application are the development tools utilized to achieve the system.

Implementation – The system must be initialized and tested for problems before being put into

use.

Output – Municipal Social Welfare and Development Jasaan Management System with SMS

Notifier.

1.3 Statement of the problem

1.3.1 General Problem

The Jasaan Municipal Social Welfare and Development (MSWD) office still uses

a manual method to retain records of its members, which causes issues such as

misplacing documents and taking longer to discover data for nearly a hundred members.

Keeping track of all records on paper is time-consuming and error-prone.

1.3.2 Specific Problem

 Traditional record retrieval and tracking took place in a huge physical location.

 Permanent record archiving and indexing is disorganized.

 Disseminating information or announcements to members one by one causes

problems and wastes time.

1.3.3 Objectives of the Study

1.3.4 General Objective


6

The main goal of this project is to ensure the preservation of permanent and

valuable papers, secured and accessible for future reference of Municipal Social

Welfare and Development Jasaan.

1.3.5 Specific Objective

 To create a MSWD mobile application that can notify the clients via SMS.

 To design an application that is easy and efficient to use.

 To create a web-based management that have an easy-to-use interface

for keeping track of clients' assistance applications.

1.4 Significance of the Study

This part of the study explained the importance of developing the system to the

following:

The admin of MSWD Jasaan. The study will make it easier for MSWD administrators

to organize the preservation and indexing of permanent records, archive and track records more

efficiently, and distribute information or announcements to members individually.

Citizens. The study is primarily designed for the end users to have a simple and quick

access for sending application criteria. Since the mobile application already meets all of their

requirement, the client will just visit the office for the interview.

Office Staff/Social Worker. Social workers or staff can do their task more efficiently

and effectively.
7

Proponents. The study may help the researchers learn more about the clients' current

circumstances. The proposed study will contribute to the completion of the requirements for

degree of Bachelor of Science and Information of Technology.

The Future Researchers. The proposed study will serve as a reference for the other of

future researchers with the same study or system.

1.5 Scope and Limitations of the study

Municipal Social Welfare and Development with SMS Notifier, a web-based system, will

be deployed in the municipality of Jasaan. Citizens of the municipality can seek help from the

MSWD office online and receive a notice through SMS. The online application was designed

and developed to work with any web browser or other web-based graphical user interfaces. It

would relate to the command functions. SMS is an abbreviation for Short Message Service,

which is a communications protocol for sending and receiving text messages that may be

combined with Internet-based services.


8

1.6 Definition of Terms

The following are the operational definitions used in the study.

MSWD (Municipal of Social Welfare and Development). A welfare that will care, protect and

develop the disadvantaged sectors to become self-reliant and productive citizens in the

community through responsive delivery of social welfare services.

SMS (Short Message Service). Commonly known as texting. It's a way to send text-only

messages of up to 160 characters between phones

LGU (Local Government Unit). LGUs play a major role in a community's development, provide

the links between the people and government, address its community's problems and concerns,

enforce policies and hold influence over its communities.


9

Social Welfare - Organized public or private social services for the assistance of disadvantaged

groups specifically, which guides the government programs that assist people in need and builds

on the idea that a government has a responsibility to protect its citizens from harm.

Record Management- Records management activities include the creation, receipt,

maintenance, use and disposal of records. In this context, a record is content that documents a

business transaction. Documentation may exist in contracts, memos, paper files, electronic files,

reports, emails, videos, instant message logs or database records.

Valuable Papers- Valuable papers and records are a type of property-casualty insurance that

covers the cost to restore or reproduce documents that have been lost or damaged by fire or

another peril.

Application - a computer software package that performs a specific function directly for an end

user or, in some cases, for another application.

Financial Assistance - is any type of monetary help or aid that a person , organizations , or

government receives.
10

Chapter II

REVIEWS OF RELATED LITERATURE AND STUDIES

2.1 SMS NOTIFICATION

In the field of communications technology, SMS is an abbreviation. It stands for Short

Messaging Service, which is a communication protocol that allows for the transmission of short

text messages from one mobile phone device to another. SMS, or text messaging, has essentially

taken over as today's mode of communication, with 74% of all mobile phone users sending and

receiving text messages. SMS technology has opened the path for the fast expansion and

advancement of text messaging, allowing users to broadcast SMS text messages not only from

mobile phones but also from computers using SMS software and public SMS gateways. The

connection between text messaging and SMS technology currently includes the use of the name
11

"SMS" to refer to the act of texting or sending text messages even when using a different

communications protocol. The "Face Recognition Attendance with SMS Notification" project is

designed to verify and track attendance using face recognition. The date and time of the recorded

attendance will be included in the SMS. The system will also provide SMS notifications to

absentees. The Construction Safety and Health Monitoring (CSHM) system is described in this

article as a web-based system for monitoring and analyzing construction safety and health

performance. Method: The design and development of CSHM involves the integration of internet

and database technologies in order to produce a fully automated safety and health management

solution. For the management of safety and health in construction, a set of performance metrics

for safety and health was developed. The following four key components of CSHM are presented

in a conceptual framework: (a) Web-based interfaces (templates); (b) knowledge bases; (c)

output data; and (d) benchmark groups. Results: The combined effect of these components

results in a system that enables rapid performance assessment of safety and health activities on

construction sites. Important management choices and remedial measures may potentially be

done using the CSHM's built-in functionalities before prospective dangers evolve into fatal or

injurious workplace incidents. As a result, the CSHM system will speed up the monitoring and

evaluation of performance, safety, and health management duties.

Innovation has made computer operation simple enough in processing record

systems, such as record production, storage, filling, and retrieval of data. People presently live in

the so-called digital world as a result of the advancement of information and communication

technologies. Even schools and colleges are becoming more involved in the digital society.

Portals are becoming increasingly popular as a method of gathering, organizing, and displaying

material in a very consistent, customizable, and customized manner. Parents will be alerted of
12

their children's grades by SMS for the revised grades. The grades will be immediately delivered

to the parents as soon as the instructors change them. In this context, the researchers are tasked

with conducting a study on the construction of an online reservation system dubbed "Online

Reservation System with SMS Notification for Josephine Abello, DMD Dental Clinic." This

allows potential guests to reserve a room whenever they want and increases sales because

personnel are not restricted to working hours. In reality, studies suggest that a 24-hour online

reservation system boosts the amount of bookings significantly. Because tricycle operations are

typically a source of income for many residents, the BTFRB is trying their best to accommodate

all transactions in their department, but despite their efforts, there are still certain things that may

be better. BTFRB continues to employ a manual approach for documenting transactions in a

logbook. All granted franchises were submitted on the Franchising Logbook for renewal, while

all approved petitions to drop the franchise were documented on the Dropping Logbook. The

franchisor has trouble tracking the status of all registered tricycle franchisees, such as expired,

renewed, canceled, and transferred franchises, using this type of data keeping. All citations

issued on that day will be logged in the violation logbook, including payment monitoring, for the

list of infractions. S. Pudasaini, A. Pathak, S. Dhakal, and M. Paudel. (2014).

2.2 MANAGEMENT SYSTEM

A management system is a set of processes, procedures, and policies that an organization

uses to ensure that it can achieve its objectives in an efficient and effective manner. Management

systems are designed to help organizations manage their resources, processes, and people to

achieve their goals and objectives. There are many different types of management systems,

including quality management systems, environmental management systems, health and safety
13

management systems, and information security management systems, to name just a few. Each

of these systems has its own set of rules, principles, and best practices that businesses may use to

put in place an effective management system. A management system, in general, consists of

several fundamental parts, such as: Planning: The company establishes its goals, objectives, and

methods for accomplishing them. Implementation is the process through which an organization

puts its plans into action, employing processes and procedures to attain its goals. Monitoring:

The organization keeps track of its progress to ensure that it is on track to meet its goals.

Evaluation: The organization assesses its performance in relation to its goals, identifies areas for

improvement, and makes adjustments as needed. Continuous improvement: The company is

always working to enhance its management system in order to keep it effective and efficient.

Organizations may improve their operations, decrease risks, and improve their reputation with

customers, workers, and other stakeholders by developing an effective management system. Don

Chew, Stern, Joel, Bennett Stewart, and Joel Stern (1998)

DSWD Caraga, Philippines, Record Management System;

"Every day, small and large businesses deal with a variety of documents, according to

Jaymer, J.M., Moyon, E.S., and Morales, E.M.O. (2021). These data could be used for historical,

demographical, social, medical, or scientific study, as well as serving as benchmarks for

measuring future activities and decisions. The Caraga Department of Social Worker and

Development (DSWD) generates records on a daily basis.

TAPIS (Technical Assistance Project Management Information System)

"According to the Technical Assistance Project Management Information System

(TAPIS) research." Social welfare is one of the Philippine government's top priorities today,
14

given that the nation has a poverty rate of 26.3%, according to the Family Income and

Expenditure Survey performed in July 2015. (Philippine Statistics Authority, 2016). The DSWD

is the federal agency in charge of dealing with such concerns in the country. Various offices,

bureaus, services, and units (OBSU) within DSWD work together to carry out the department's

tasks. This research focuses specifically on the DSWD Technical Assistance Unit (TAU), which

is in charge of administering financing for DSWD programs. These initiatives largely contribute

to the enhancement of the DSWD's programs. TAU's major purpose is to offer social protection

services efficiently and effectively through coordinated, harmonized, and timely technical

assistance implementation. ' (https://shorturl.ae/NId4R)

RECORD MANAGEMENT SYSTEM FOR DEPARTMENT OF SOCIAL WELFARE

AND DEVELOPMENT OF BALETE, BATANGAS

"According to Santos and Juan (2018), an organization runs information, and it has a

particular way of gathering, storing, and having quick fill-up forms. Information for collecting

and storing reports is compiled with pen and paper; nevertheless, management systems have

completely revolutionized the process of applying forms in each program. The developed

system’s concern is to help the Department of Social Welfare and Development resolve some

problems regarding their daily transactions. This department at the Municipality of Balete,

Batangas, provides forms for the Department of Social Welfare and Development. It has a

program for the Provision of Social Case Study Report, Provision of Disaster Relief Assistant,

Provision of Solo Parent Identification Card, Provision of Certificate of Indigency, Early


15

Childhood Care and Development Program, and Provision of Senior Citizen Identification Card

(https://shorturl.ae/cpC3l).

An Assessment of Record Management System in Establishment Division of Two

Universities in Nigeria

"According to Udensi and Akor (2014), record management; establishment division;

information; filing The major purpose of this study was to assess the record management systems

at the Federal University of Technology, Minna, Nigeria, and Ibrahim Badamasi Babangida

University, Lapai, Nigeria. In carrying out this study, four (4) research questions were posed.

The study sample population comprised 88 staff members (46 from the establishment division of

the Federal University of Technology, Minna, and 42 from the establishment division of the

Ibrahim Badamasi Babangida University, Lapai). The instrument used for data collection was a

questionnaire. The research questions were answered using frequency and percentages. The

major findings of the study revealed ineffectiveness in record management practices,

incompetent personnel, inadequate infrastructural facilities, and constant power failure. Based on

these findings, the following recommendations were made: efforts should be made to provide a

standby generator as an alternative to power supply, train staff to handle the universities’ records,

and provide adequate funding and infrastructural facilities (https://shorturl.ae/vvdRr)’.


16

Chapter III

METHODOLOGY

This chapter discusses methods used in the research .This provides the flow how the

study is done.

3.1 Information Gathering

3.1.1 Research Setting


17

The research was carried out in the Municipality of Jasaan, Jasaan Misamis Oriental, and

15 barangays to make the work one of the critical steps for the study's success.

Figure 2 Map of the Municipality of Jasaan.

3.2 Research Design

This study was made by means of developmental research, which refers to the study and

analysis of the economic, social, and political factors that influence the growth and progress of a

particular region or community. This research is typically conducted by economists, social

scientists, and other experts who specialize in the field of development studies. Developmental

research can be conducted at different levels, including local, national, and international levels.

The research can focus on a wide range of topics, including poverty reduction, economic growth,

social welfare, environmental sustainability, and political stability. The ultimate goal of

development research is to identify the factors that contribute to the development of a region or

community and to develop effective policies and programs to support that development.
18

Typically, development research employs a variety of approaches, including

qualitative and quantitative research methods. Development research findings are used to guide

policy choices and program implementation. Similarly, a development research study may assess

the effects of a particular policy or program on a community and make recommendations to

improve its efficacy. In conclusion, development research is an essential discipline that seeks to

comprehend and address the economic, social, and political elements that impact the growth and

success of a certain region or community. The findings of the research are used to guide policies

and initiatives that can support sustainable development and improve the quality of life for

people living in such areas.

Figure 3

System Development Life Cycle


19

SDLC stands for Software Development Life Cycle, which is a framework for

developing software applications. It is a process used by software development teams to plan,

design, build, test, and deploy software applications.

The SDLC typically consists of six phases:

Planning: In this phase, the development team identifies the software requirements and

objectives, assesses the feasibility of the project, and creates a project plan. The development

team collects requirements from several stakeholders such as customers, internal and external

experts, and managers to create a software requirement specification document.

Requirements Gathering: In this phase, the development team works with the stakeholders to

identify and document the software requirements. It involves gathering information about the

users needs and goals for the project which will guide the development team in creating a

solution that meets those needs.

Design: In this phase, the development team creates a high-level design for the software

application, including the architecture, user interface, and database design. System Design helps

in specifying hardware and system requirements and also helps in defining overall system

architecture. The system design specifications serve as input for the next phase of the model.

Development: In this phase, the development team writes the code for the software application,

following the design specifications. The development team writes code, performs unit testing,

and integrates components to create a functional software solution. The development phase also

involves regular communication and collaboration to ensure that the software meets their needs

and expectations.
20

Testing: In this phase, the development team tests the software application to identify and fix

bugs and ensure that it meets the requirements. It includes various types of testing such as unit

testing, integration testing, system testing and acceptance testing.

Following the SDLC process helps ensure that software applications are developed in a

structured and controlled manner, reducing risks and increasing the likelihood of success.

3.3 Requirement Gathering

In order to gather the requirements for developing a prototype of the Municipal Social

Welfare and Development Management System with SMS Notifier, the researchers interviewed

MSWD beneficiaries as well as the administrator to learn about their concerns and suggestions

for the application and system. The researcher created the MSWD Jasaan Management System

with SMS Notifier for further information and announcements using development technologies

that would be employed in the project (PHP, CSS, MYSQL, and so on).

3.4 Unit of analysis

The term "unit analysis" refers to "the level of aggregation of the data collected during

the following data analysis stage." The Municipal Social Welfare Development Jasaan

Management System with SMS Notifier is the focus of this study's unit analysis. This study

focuses on assisting MSWD Jasaan social protection programs, specifically PWDs, single

parents, senior citizens, children in need of social protection, youth in need of special protection,

women in especially difficult circumstances, family heads, and other needy adults, by developing

an application that program participants can easily access. Rather of the traditional method, the
21

researcher will develop a web-based system that will save all of the documents in a database that

will maintain track of both previous and present data. The tactics of developers will help the

industry's efficiency and effectiveness.

3.5 Data source

Data is information that contains facts that may be used to discuss and decide how to

reply to survey questions. The study's data source is a subject who can collect data for many

objectives. The Google Forms platform is used by researchers to conduct a survey for MSWD

Jasaan members. Individual interviews with the administrator of MSWD Jasaan The data in this

study is based on a qualitative approach and frequently depends on data gathering methods. The

researchers compared their function and features to those of other investigations that had

previously been conducted.

3.6 Respondents and Sampling

The respondents will be recruited from the Municipality of Jasaan's 15 barangays, with

referrals to the MSWD headquarters. The researchers will guarantee that the responders are

Jasaan residents. An interview with the director of the MSWD department has been scheduled as

part of the study, and respondents will be questioned using an online platform using Google

Forms. As a result, the following participants or interviewees comprise the sample population for

this study: MSWD Head, PWD, Senior Citizen, and Solo Parent; Children in Need of Social

Protection; Youth in Need of Special Protection; Women in Especially Difficult Circumstances;

Family Head; and Other Needy Adult.


22

Participants in this study are chosen using targeted sampling procedures. This sampling

approach allows the user to choose samples solely from subpopulations where the likelihood of

receiving the intended beneficiaries is higher. This is performed by selecting citizens from a

subset who exhibit a characteristic that indicates a higher possibility of the benefits being

present. Targeted sampling refers to samples that are deliberately selected based on your research

goals. This strategy may be used by researchers to collect relevant and important data and to

answer research questions.

3.7 Data Gathering Instruments and Procedure

This research primarily proposes an efficient and effective technique for administering

the MSWD Jasaan Management System using SMS Notifier for requirement collection. The

head or staff continues to rely on traditional retrieval and tracking of records housed in a massive

physical location. This system takes a long time, and data or files are sometimes lost as a result.

The researcher devised the concept of developing an application-integrated web-based

management system in which users such as solo parents, PWDs, and senior citizens, children in

need of social protection, youth in need of special protection, women in particularly difficult

circumstances, family heads, and other needy adults from Jasaan municipalities will download

the app from the app store and sign-in or sign-up for user authentication. This data will be

recorded in a database overseen by the MSWD administrator.


23

CHAPTER IV

DATA PRESENTATION, INTERPRETATION AND ANALYSIS

This chapter presents the data analysis, the study findings, and the nominal scale

questionnaire result. The findings are related to the study's research topics. In MWSD Jasaan,

data were processed to identify, explain, and elaborate the interaction between users and the

system itself.

4.1 Requirements Specification


24

4.1.1 Schedule Feasibility

Table 1 Gantt Chart

4.1.2 Requirements Modeling

a) User Definition

 The user needs a stable internet connection.

 The user admin needs pc or laptop to access the web-based application through the

browser.

 The application requires the user to answer the given information.


25

 The application sends verification code to the verified user.

 The application integrated web-page must have an admin log-in.

 The application integrated web-page must allow the admin to manage reports.

 The application integrated web-page must allow the admin to log-out.

 The user needs a mobile phone in order to download and install the mobile

application.

 View Documents.

b) System Module Specification

Mobile Application Module

This module provides the functionality for clients to ask assistance and add necessary

details. Users of the system namely MSWD Jasaan Management System with SMS

Notifier must be provided the following functionality.

□ Create an account

□ Verify user

□ Log in to the system

□ Manage their account

□ Apply for Assistance

□ Receive Appointment for Interview


26

Management System Module

This module exclusively serves the administrator needs. It will not be accessible to any

other system user such as MSWD staff and other non-authorized personnel.

□ Sign In/Sign out

□ Manage Clients

□Add/Update

□ View Documents

□ Approved/Disapproved

□ Setting an Appointment for interview

□ Release Assistance

4.2 Data and Process Modeling

4.2.1 Context Diagram


27

Figure 4 Context Diagram

The diagram depicts the system's context. The context diagram depicts the system under

examination as a single high-level process, followed by the system's connection with various

external entities, such as users. The system administrator will be in charge of managing the

complete system; essentially, the system administrator's task will be to handle all of the reports

that are included, such as receiving requirements, arranging appointments, approving clients,

publishing announcements, and sending updates. Users can transmit personal information, obtain

confirmation, and inquire about their accounts.


28

4.2.2 Functional Decomposition

MSWD SYSTEM

MANAGEMENT

USER ADMIN

DASHBOARD FORMS ACCOUNTS DASHBOARD


LOGIN MUNICIPAL

NAME
REQUIREMENTS APPOINTMENT BARANGGAY
VERIFICATION ANNOUNCEMENTS
NTS
CODE
CONTACT# ANNOUNCEMENTS
UPDATES PERSONAL S
DATA
SIGN UP

ASSISTANCE

Figure 5 Functional Decomposition

The functional breakdown of the municipal social welfare and development program in

Jasaan is illustrated. The user interface allows users to fill out any required forms or criteria. A

login form is displayed to the user for system access. After registering, the system will generate a

verification code for the user. The admin interface also has a login. The administrator can

monitor the accounts of registered users. The administrator can also see who completed the

necessary paperwork or satisfied the requirements.


29

4.2.3 System Flowchart

User

Figure 6 FLOWCHART USER


30

Admin

Figure 7 FLOWCHART ADMIN

The system flowchart is shown in Figures 6 and 7. The user will log in, and if they do

not already have an account, they will sign up. The system will ask for their phone number upon

registration and will provide a verification code. The system will take the user to their profile

when they have validated their account. When they provide the required documents, such as

barangay indigence, birth certificates, and so on, the admin or staff will receive and review them.
31

If all of the prerequisites are completed, the administrator will authorize the user and schedule an

appointment.

4.2.4 Object Modeling

a) Use Case Diagram

Figure 8 Use Case Diagram

A use case diagram is a method of summarizing the details of a system and its users. The

newly created system's use case is depicted in Figure 8. The primary players are MSWD's system

administrators. The client will only be a system participant.


32

4.3 RISK ASSESSMENT VULNERABILITIES

Threat Vulnera Assets Impact Ris Control Recommendation


bility k
Unauthorized data Insufficie User loss of Hig Implement proper data
access by an nt data data user h encryption for storage and
attacker encryptio such as data transmission of user data
n in persona security
Medium storage l and
and informa privacy,
transmiss tion and as well
ion financia as
l potentia
High informa l user
tion financia
l loss
High High

Unauthorized access Weak App Unautho Low Implement multi-factor


to the app's backend password function rized authentication for all users and
server s or lack ality, access administrators
of multi- user to user
Medium factor data data,
authentic unautho
ation High rized
access
Medium to
device
function
33

ality,
potentia
l for
malware
injectio
n

Medium
Poor user Insufficie The Unautho Low Use appropriate user
authentication nt user mobile rized authentication procedures,
name and applicat access such as user name and
password ion to the password or multi-factor
authentic itself as mobile authentication, to safeguard
High ation well as applicati access to the mobile
methods the on and application.
for the informa data
mobile tion it stored
applicatio contains on it
n
High Medium
Low
34

4.4 System Design

4.4.1 Output and User-Interface Design

Admin User

Figure 9 Admin login


Home Page

✓Input email address and password


✓Click Log In to show admin dashboard
35

Figure 10 Admin Dashboard

✓ Select home to show recent announcement


✓ Show an appointments
✓ Review Applications
36

Figure 11 Admin- Announcement

✓ Input the upcoming announcement


✓Update and delete announcement

Figure 12 Beneficiary Management

✓ Click beneficiary management to view the list of beneficiaries


✓ Click the name to see the information
37

Figure 13 Admin Appointment Management


✓ Click the assistance to see the list of applicants
✓ click the name to view the information
38

Figure 14 Clients Identity Information


✓Click applicants profile to see the user personal information

Figure 15 Clients Application details


39

Figure 16 Admin- Report

MOBILE APPLICATION
40

Figure 17 User login page

✓ Click input mobile number

✓ Click input password

✓ Click Sign Up

Figure 18 User Login Verification


41

✓Click input number to verify

✓Click verify code


42

Figure 19 User Register Account

✓Click input new password

✓Click confirm password


43

Figure 20 Clients Identifying Information

✓Clients need to fill up the identifying Information to proceed for the assessment
44

Figure 21 User Assessment Page

✓ Click Apply now to send requirements and get a reference number.


45

Figure 22 User Page

✓User Profile

✓Sign out
46

Figure 23 User Home Page

✓Home Page

✓Announcements

✓User History
47

4.5 Data Design

4.5.1 Entity Relationship Diagram

Figure 24 Entity Relationship Diagram

A graphical depiction of the entities, properties, and connections that comprise a system

or organization is known as an entity relationship diagram (ERD). ERDs are frequently used in

database design to illustrate a database's structure and the interactions between its many

components.

Entities are represented by rectangles, characteristics by ovals, and connections

between entities are represented by lines linking the entities in an ERD. A relationship's
48

cardinality (how many instances of one thing are associated to how many instances of another

entity) is sometimes denoted using symbols such as crow's feet or diamonds.

4.5.2 Data Dictionary

Field Name Data Type Value

Key VARCHAR Not null

Created DATETIME Not null

user_id BIGNIT Not null

Table 3 Admin Table

Field Name Data Type Value


Id INTEGER Not null

Password VARCHAR Not null


last_ login DATETIME
system_id VARCHAR
avatar VARCHAR Not null
Email VARCHAR Not null
mobile_number VARCHAR Not null
is_superadmin BOOL Not null
created_at DATETIME Not null
is_admin BOOL Not null
updated_at DATETIME Not null
49

Table 4 User Table

Field Name Data Type Value


Id INTEGER Not null

beneficiary_family_composition TEXT
interview_schedule_date DATETIME
release_schedule_date DATETIME
approve_by VARCHAR
interviewed_by VARCHAR
released_by VARCHAR
created_at DATETIME Not null
updated_at DATETIME Not null
user_id BIGINT Not null
Assessment TEXT
client_identifying_information TEXT
reference_no VARCHAR
application_status VARCHAR
Attachment TEXT
Assistance VARCHAR
Remarks VARCHAR
Cash DECIMAL Not null
Proof VARCHAR

Table 5 Assistance applicant form


50

Field Name Data Type Value


Id INTEGER Not null

Firstname VARCHAR
Middlename VARCHAR
Lastname VARCHAR
Extension VARCHAR
Sex VARCHAR
Date_or_birth DATETIME
Region VARCHAR
Province VARCHAR
City_or_municipality VARCHAR
District VARCHAR
Barangay VARCHAR
No_street_or_purok VARCHAR
Place_of_birth VARCHAR
Civil_status VARCHAR
Religion VARCHAR
Nationality VARCHAR
Highest_educational_attainment VARCHAR
Skills_or_occupation VARCHAR
Created_at DATETIME Not null
User_id BIGINT
Updated_at DATETIME Not null

Table 6 Beneficiary
51

Field Name Data Type Value


Id INTEGER Not null

Create_at DATETIME Not null


Updated_at DATETIME Not null
Banner VARCHAR
Title VARCHAR
Description TEXT
Viewers INTEGER
Author VARCHAR

Table 7 Announcement
52

4.6 System Architecture

Figure 25 System Architecture

With an SMS notifier, this diagram depicts the system architecture of the Municipal

Social Welfare and Development Management System. Users can access the program only if

they have an internet connection. Following registration, the system will provide the user with an

authentication verification code. Each user's data will be returned to the database, and the admin

will get the data provided by the applicants or clients. The admin will send them an SMS update

to let them know if their application was granted or denied and if they are ready for the

interview.

4.7 Development

4.7.1 Software Specification


53

 Visual Studio- is a prominent integrated development environment (IDE).

Software developers use it to create a wide range of applications,

including desktop applications, online apps, mobile applications, and

games. Visual Studio contains a number of capabilities that help

developers design, debug, and deploy programs more easily features that

make it easier for developers to create, debug, and deploy their

applications.

4.7.2 Hardware Specification

 Mobile application minimum requirements: Ram 4 GB, storage 15 GB.

 Runs only on Android phones at the moment.

4.7.3 Program Specification

 Functional requirements.

 Non-functional requirements.

 Keyboard must work properly.

 The buttons in the application and web-based application are all

functioning.

 The system prompts the user when excess input of mobile numbers is

inputted.

 Password is hidden.

 All necessary fields are required.

 Data is saved properly after submission.

 The graphic user interface design used is very simple and responsive.
54

4.7.4 Program Environment

The researchers ensure that the application will fulfill the user and client standards by
analyzing the system and the user's requirements. Researchers will be more resourceful in
developing the application if they have access to an open interaction environment.

Front End
To build this front end, the supporters will utilize Visual Studio as the scripting
language, which is used to produce web pages, and CSS codes, which may store
design information.

The back end


It is a server-side software that helps the front end indirectly. The supporters plan to
use Visual Studio, JS, and HTML. Python is a computer programming language that
is frequently used to create websites and applications, automate operations, and
analyze data. Python is a general-purpose programming language, which means it can
be used to develop a wide range of applications and is not specialized for any
particular problem.

Notification
A SMS API is well-defined software interface which enables code to send short
messages via a SMS Gateaway SMS APIs are used to allow web applications to
easily send and receive text message through logic written for standard web
frameworks.
55

4.7.5 Deployment Diagram

Figure 26 Deployment Diagram

Figure 26 shows the deployment process of the application and web server. Each

component of the mobile application has a distinct role in the overall application behavior and

can be activated independently. The mobile application is made up of many components that

depend on the activities, services, or any other operations of a system. The admin goes through

the web to access the system and with its database and perform the required task.

4.8 Test Plan


56

The suggested system will be tested and ideas for future system enhancements will be

made. "Municipal Social Welfare and Development Jasaan Management System with SMS

Notifier" The proposed system aims to fulfill the deadlines for developing the system and its

features, as well as installing or implementing the system. And, before installing the system, we

evaluate and test the whole system to ensure that it satisfies all of the system's requirements. The

results of the system assessments and testing should be adequately recorded in order to verify

and maintain if all system features are operational.

4.8.1 Testing

The subset software will be bug and error tested. Following the development of the

program, the team will prepare a dry run for the system to be tested in order to determine if the

system is working efficiently and effectively on the intended platform, as well as if it meets the

needs or desires of the users or clients in terms of the system's requirements or features.

4.8.2 Unit Testing

Unit testing is a software testing approach that isolates specific units or components of a

software program from the rest of the application. This type of testing is done in social protection

programs for people with disabilities, single parents, senior citizens, children in need of social

protection, youth in need of special protection, women in particularly difficult circumstances,

family heads, and other needy adults to ensure that each component works as intended. Unit

testing is a software development approach in which individual program units or components are

evaluated in isolation to verify they function as intended. This approach assists developers in

identifying and correcting errors early in the development process, resulting in higher-quality

and more dependable software.


57

Developers use unit testing to build simple, automated tests that check the behavior of

each unit of code. These tests are often run whenever the code is altered or updated to ensure that

no new problems or issues have been introduced.

4.9 System Testing

The system has been tested to ensure that it is operationally sound. The primary

purpose of this testing was to confirm that the system met all of the specifications. System

testing is a sort of software testing in which the complete system or application is evaluated as a

whole rather than individual components or parts. It is carried out to ensure that the system or

application satisfies its specifications and performs as expected in its intended environment.

During system testing, testers examine the behavior of the program in a variety of scenarios,

including conventional use cases and edge cases. They may also do performance testing, security

testing, and compatibility testing to verify that the application works properly in a variety of

contexts and scenarios. One of the primary advantages of system testing is that it helps uncover

and fix flaws that may not be obvious until the complete system has been integrated and tested.

Interface difficulties between distinct components or systems, performance bottlenecks, and

security vulnerabilities are examples of such concerns.


58

a) Performance of the System Usability Scale result

The proponents ensured that this procedure would reliably measure the relevant

result regarding the usability of a range of innovative software system.

% of parti cipants who thought that the system cover


all the specifi ed tasks and user objecti ves.
Excellent Very Satisfactory Satisfactory Good Fair

9%

10%

23% 59%

Figure 27 Illustrates users that they like the system cover all specified task and user objectives.
59

% of parti cipants who found the system provide


correct results.
Excellent Very Satisfactory Satisfactory Good Fair

28%

72%

Figure 28 shows that the users did not find that the system provide un-correct results.

% of parti cipants who thought that the system


quickly respond.
Excellent Very Satisfactory Satisfactory Good Fair

11%

25%

64%

Figure 29 shows that the user may believe that the system quickly respond.
60

% of parti cipants thought that the user can easily


operate and control the mobile applicati on.
Excellent Very Satisfactory Satisfactory Good Fair

28%

72%

Figure 30 illustrates that the users can easily operate and control the mobile application.

% of parti cipants who believe that the user learn to


use the system easily.
Excellent Very Satifactory Satisfactory Good Fair

28%

72%

Figure 31 shows that the user learn to use the system easily.
61

% parti cipants who thought that the system user in -


terface enable pleasing and sati sfying interacti on for
the user.
Excellent Vey Satisfactory Satisfactory Good Fair

1.4

3.2

8.2

Figure 32 shows that the user interface enable pleasing and satisfying for the user.

% of parti cipants who believed that the system


ensures that the data shared are accessible by au -
thorized person.
Excellent Very Satisfactory Satisfactory Good Fair

28%

72%

Figure 33 shows that the user shared data is accessible only by authorized person.
62

% parti cipants thought that the services are au -


tonomous.
Excellent Very Satisfactory Satisfactory Good Fair

28%

72%

Figure 34 shows that the services of the system are autonomous.

% parti cipants who felt that they can easily operate


and control the mobile applicati on
Excellent Very Satisfactory Satisfactory Good Fair

11%

25%

64%

Figure 35 refers to the user who was really satisfied to operate and control the mobile

application.
63

% of parti cipants who found the system uti lize


resource effi ciently.
excellent very satisfactory satisfactory good fair

11%

25%

64%

Figure 36 Illustrates that the system utilize resource efficiently to user.


64

CHAPTER V

SUMMARY OF FINDINGS, CONLUSIONS, AND RECOMMENDATIONS

5.1 Summary of Findings

In this study, it was made to aid the records officer and the department in the storage and

retrieval of records. MSWD mobile application include the following features; Beneficiaries are

instantly informed via SMS, Accept and assess a online and Management system. The study

specifically aimed to; help beneficiaries for easy, fast access and sending requirements through

the application; help the staffs for easy, fast access and sending requirements through

application. The newly developed system will be deployed first to the beneficiaries of MSWD

and it is beneficial also for the administrator to ensure the preservation of permanent and

valuable papers, which are secured and accessible for future reference.

5.2 Conclusion

This study helps both beneficiaries and staffs of the MSWD to make their work easier

and faster. The newly developed system helped the admins to monitor the accounts of the users

and their forms easily unlike the traditional one they need to process the forms one by one.

5.3 Recommendation

With the newly developed system, the researchers suggest the following:

1. The newly developed system to be implemented in MSWD should have a free SMS to be

used.

2. Encourage the beneficiaries and admins to use the system.


65

3. Conduct future researches in order to improve the quality of the system specifically on

the:

o Improvement of the system to be use offline

o Improvement of the System Security

References

[1]Jaymer, J.M., Moyon, E.S. & Morales, E.M.O (2021). OCR based Document Archiving and
Indexing using PyTesseract: A Record Management System for DSWD Caraga, Philippines
(College of Computing and Information Sciences Caraga State University Ampayon, Butuan
City, Philippes).

[2]Tangkeko, M., Coronel, N. et al (2017) Technical Assistance Project Management


Information System (TAPIS) Presented at the DLSU Research Congress 2017 De La Salle
University, Manila, Philippines June 20 to 22, 2017

[3]Implementation of Social Welfare and ... - Repository.cpu.edu.ph.

[4]DSWD Issuances, https://www.dswd.gov.ph/issuances/.

[5]Implementation of Social Welfare and ... - Repository.cpu.edu.ph.


https://repository.cpu.edu.ph/bitstream/handle/20.500.12852/905/SGS_MSSW_CambelJG
_2016_Ab_Sub.pdf?sequence=

[6] MSWD Online Assistance Request and Monitoring System With SMS Notification
https://www.scribd.com/document/529718437/MSWD#

[7] McHugh, Jason, et al. "Lore: A database management system for semistructured data." ACM
Sigmod Record 26.3 (1997): 54-66. https://dl.acm.org/doi/abs/10.1145/262762.262770
66

[8] T. L. O. Pandes, C. D. Omorog and R. B. Medrano, "LeMTrac: Legislative Management and


Tracking System," 2018 IEEE 10th International Conference on Humanoid, Nanotechnology,
Information Technology,Communication and Control, Environment and Management
(HNICEM), Baguio City, Philippines, 2018, pp. 1-6, doi: 10.1109/HNICEM.2018.8666260.
https://ieeexplore.ieee.org/abstract/document/8666260

[9] Abdulgani, Montadzah, et al. "Event Management System With SMS Notification for
Mindanao People’s Care Foundation, Inc." Psychology and Education: A Multidisciplinary
Journal 3.7 (2022): 600-609. https://scimatic.org/show_manuscript/481
67

Appendices
68

A. Survey Questioner

Name: _____________________ Date: ___/___/___

Sex:_______________________ Address: _________

System Usability Scale


Instructions: For each of the following statements, mark one box that best describes your
reactions to the SYSTEM TODAY. (1)

QUESTIONS Excellent Very Satisfactory Good Fair


Satisfactory

1.The system ensures that


the data

shared are accessible by


authorized person?

2.Does the system provide


correct results?

3.Does the system utilize

resources efficiently?

4.Services are autonomous?

5.Can the user learn to use


the system

easily?
69

6.Does the system user


interface enable pleasing and
satisfying interaction for the
user?

7.Does the user can easily


operate and control the
mobile application?

8.Does the system cover all


the specified tusks and user
objectives?

9.How quickly the system


respond?

10.Can the user learn to use


the system

easily?
70

Admin Guide

Urls.py

from django.urls import path

from app.api.views import (

AuthVerificationView,

AuthSendVerificationView,

UserLoginAPIView,

UserRegisterAPIView,

UserProfileAPIView,

UserAssistanceApplicantFormAPIView,

UserAssistanceApplicantListAPIView,

UserCheckApplicationStatusAPIView,

UserAnnouncementListAPIView,

UserAnnouncementFormAPIView,

AdminLoginAPIView,

AdminDashboardDataAPIView,

AdminAppointmentsListAPIView,

AdminAssistanceApplicantListAllAPIView,
71

AdminAssistanceApplicantFormAllAPIView,

AdminAssistanceApplicantListAPIView,

AdminAssistanceApplicantFormAPIView,

AdminBeneficiaryListAPIView,

AdminBeneficiaryFormAPIView,

AdminAnnouncementListAPIView,

AdminAnnouncementFormAPIView,

AdminChartReportAPIView,

LogoutAPIView,

urlpatterns = [

path("verify/", AuthVerificationView.as_view()),

path("send-verification/", AuthSendVerificationView.as_view()),

path("login/", UserLoginAPIView.as_view()),

path("logout/", LogoutAPIView.as_view()),

path("register/", UserRegisterAPIView.as_view()),

path("profile/", UserProfileAPIView.as_view()),

path("profile/<int:pk>/", UserProfileAPIView.as_view()),

path("apply-assistance/", UserAssistanceApplicantFormAPIView.as_view()),

path("applications/", UserAssistanceApplicantListAPIView.as_view()),

path("applications/<int:pk>/", UserAssistanceApplicantFormAPIView.as_view()),

path("check-applications/", UserCheckApplicationStatusAPIView.as_view()),

path("announcements/", UserAnnouncementListAPIView.as_view()),

path("announcement/<int:pk>/", UserAnnouncementFormAPIView.as_view()),

path("admin-login/", AdminLoginAPIView.as_view()),

path("admin-dashboard-data/", AdminDashboardDataAPIView.as_view()),
72

path("admin-appoinments/", AdminAppointmentsListAPIView.as_view()),

path("admin-applications/", AdminAssistanceApplicantListAllAPIView.as_view()),

path("admin-applications/form/<int:pk>/",
AdminAssistanceApplicantFormAllAPIView.as_view()),

path("admin-applications/<str:slug>/",
AdminAssistanceApplicantListAPIView.as_view()),

path("admin-applications/<str:slug>/form/<int:pk>/",
AdminAssistanceApplicantFormAPIView.as_view()),

path("admin-beneficiaries/", AdminBeneficiaryListAPIView.as_view()),

path("admin-beneficiaries/<str:slug>/", AdminBeneficiaryFormAPIView.as_view()),

path("admin-announcements/", AdminAnnouncementListAPIView.as_view()),

path("admin-announcement/", AdminAnnouncementFormAPIView.as_view()),

path("admin-announcement/<int:pk>/", AdminAnnouncementFormAPIView.as_view()),

path("admin-chart-report/", AdminChartReportAPIView.as_view()),

Views.py

import json

import random

import datetime

import requests

from dateutil import parser

from operator import itemgetter

from django.conf import settings

from django.core.files.storage import FileSystemStorage

from django.http import Http404

from django.db.models import Q

from django.db import IntegrityError

from django.contrib.auth import authenticate, login, logout


73

from rest_framework.authtoken.models import Token

from rest_framework.authentication import SessionAuthentication

from rest_framework.permissions import IsAuthenticated

from app.models import (

User,

BeneficiaryProfile,

AssistanceApplicantForm,

Announcements,

from app.serializers import (

UserSerializer,

BeneficiaryProfileSerializer,

AssistanceApplicantFormSerializer,

AnnouncementsSerializer,

from utils.strong_password_policy import StrongPasswordPolicyUtils

from utils.exceptions import HumanReadableError

from utils.views.api import API

STRONG_PASSWORD_POLICY_UTILITY = StrongPasswordPolicyUtils()

class Mixins:

def filter_mobile_number(self, mobile_number) -> str:

return mobile_number.replace("+63", "")

def custom_upload_file(self, file, location, base_url, timestamp):

""""""
74

file_system_storage = FileSystemStorage(location=location, base_url=base_url)

filename = file.name.split(".")

name = filename[0]

extension = filename[-1]

replace_char_name = name.lower().replace(" ", "-")

custom_file_name = f"{replace_char_name}.{timestamp}.{extension}"

url_file_name = file_system_storage.save(custom_file_name, file)

upload_file_url = file_system_storage.url(url_file_name)

return name, extension, f"{settings.MEDIA_URL}{upload_file_url}"

def send_bulk_sms(self, recipient, message):

""""""

if not settings.ALLOW_SMS:

return {}

response = requests.post("https://api.sms.fortres.net/v1/messages",
auth=("8715ed2f-4b38-4445-8086-b4146f04f556",
"7d7gburv38itwZCAh2DhcfupqO8SjW15NcivIwPK"), data={

"recipient": recipient,

"message": message

})

if response.status_code == 200:

return True

else:

return {}

def send_schedule_sms(self, recipient, message):

""""""

if not settings.ALLOW_SMS:

return {}
75

response = requests.post("https://api.sms.fortres.net/v1/messages",
auth=("8715ed2f-4b38-4445-8086-b4146f04f556",
"7d7gburv38itwZCAh2DhcfupqO8SjW15NcivIwPK"), data={

"recipient": recipient,

"message": message

})

if response.status_code == 200:

return True

else:

return {}

def send_otp_sms(self, recipient):

""""""

if not settings.ALLOW_SMS:

return {}

response = requests.post("https://api.sms.fortres.net/v1/messages",
auth=("8715ed2f-4b38-4445-8086-b4146f04f556",
"7d7gburv38itwZCAh2DhcfupqO8SjW15NcivIwPK"), data={

"recipient": recipient,

"message": "Your One-Time PIN is {otp}. Please do not share this with
anyone. Ref# ABC-000000"

})

if response.status_code == 200:

return response.json()

else:

return {}

class AuthVerificationView(API, Mixins):

def post(self, request, format=None) -> dict:


76

try:

payload = request.data

account_exist = True

message = ""

try:

user_account = User.objects.get(

Q(mobile_number=self.filter_mobile_number(payload["mobile_number"]))

or Q(email=payload["email"])

message = "Can't continue, Mobile number is already been used."

except User.DoesNotExist:

account_exist = False

response = {

"message": message,

"data": {

"used": account_exist,

},

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class AuthSendVerificationView(API, Mixins):

def post(self, request, format=None) -> dict:

try:

payload = request.data

code = random.randint(111111, 999999)

result =
self.send_otp_sms(self.filter_mobile_number(payload["mobile_number"]))
77

if result:

code = result["data"][0]["otp"]

response = {

"message": "Verification sent!",

"data": {

"code": code,

},

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class UserLoginAPIView(API, Mixins):

def post(self, request, format=None) -> dict:

try:

payload = request.data

try:

user_account = User.objects.get(

Q(mobile_number=self.filter_mobile_number(payload["mobile_number"]))

or Q(email=payload["email"])

except User.DoesNotExist:

self.raise_error(title="Error", message="Invalid username or


password.")

user = authenticate(

system_id=user_account.system_id, password=payload["password"]

if user != None:

login(request, user)

token, created = Token.objects.get_or_create(user=user)


78

try:

beneficiary_profile = BeneficiaryProfile.objects.get(

user=request.user

serializer = BeneficiaryProfileSerializer(beneficiary_profile)

profile = serializer.data

except BeneficiaryProfile.DoesNotExist:

profile = {}

applications = AssistanceApplicantForm.objects.filter(

user=request.user, application_status__icontains="Cancelled"

response = {

"message": "Signin successfully.",

"data": {

"token": str(token),

"profile": profile,

"has_processing_application": applications.exists(),

},

return self.success_response(response)

else:

self.raise_error(title="Error", message="Invalid username or


password.")

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class LogoutAPIView(API):

permission_classes = [IsAuthenticated]

def get(self, request, format=None) -> dict:


79

try:

user_has_token = Token.objects.filter(user=request.user).count()

if user_has_token:

request.user.auth_token.delete()

logout(request)

response = {"message": "Signout successfully."}

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class UserRegisterAPIView(API, Mixins):

def post(self, request, format=None) -> dict:

try:

payload = request.data

token = self.create_user(request, payload)

try:

beneficiary_profile =
BeneficiaryProfile.objects.get(user=request.user)

serializer = BeneficiaryProfileSerializer(beneficiary_profile)

profile = serializer.data

except BeneficiaryProfile.DoesNotExist:

profile = {}

response = {

"message": "Signin successfully.",

"data": {"token": token, "profile": profile},

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:


80

return self.server_error_response(exc)

def create_user(self, request, payload: dict) -> str:

is_strong_password,

password_requirements,

) = STRONG_PASSWORD_POLICY_UTILITY.is_strong_password(

password=payload["password"]

if not is_strong_password:

self.raise_error(title="Error", message=", ".join(password_requirements))

user_count = User.objects.exclude(system_id="MSWDADMIN-001").count()

user_id = str(user_count + 1).zfill(5)

system_id = f"MSWDUSER-{user_id}"

try:

user = User.objects.create(

system_id=system_id,

mobile_number=self.filter_mobile_number(payload["mobile_number"]),

user.set_password(payload["password"])

user.save()

except IntegrityError as error:

self.raise_error(title="Error", message="Mobile number is already used.")

user_login = authenticate(

system_id=user.system_id, password=payload["password"]

login(request, user_login)

token, created = Token.objects.get_or_create(user=request.user)

return str(token)
81

class UserProfileAPIView(API, Mixins):

permission_classes = [IsAuthenticated]

def get_object(self, pk):

try:

return BeneficiaryProfile.objects.get(pk=pk)

except BeneficiaryProfile.DoesNotExist:

raise Http404

def get(self, request, pk: int, format=None) -> dict:

try:

beneciary = self.get_object(pk)

serializer = BeneficiaryProfileSerializer(beneciary)

data = serializer.data

data["avatar"] = beneciary.user.avatar

response = {"data": data}

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

def post(self, request, format=None) -> dict:

try:

payload = request.data

payload["user"] = request.user.id

serializer = BeneficiaryProfileSerializer(data=payload)

if serializer.is_valid():

serializer.save()

response = {
82

"message": "Saved successfully.",

"data": {"profile": serializer.data},

return self.success_response(response)

else:

self.raise_error(title="Error", message="Invalid data.")

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

def put(self, request, pk: int, format=None) -> dict:

try:

payload = request.data

beneciary = self.get_object(pk)

if request.FILES.get("avatar", None):

timestamp = int(datetime.datetime.today().timestamp())

uploaded_file = request.FILES["avatar"]

location = f"{settings.MEDIA_ROOT}/announcements"

base_url = "announcements"

name, extension, upload_file_url = self.custom_upload_file(

uploaded_file, location, base_url, timestamp

serializer = BeneficiaryProfileSerializer(beneciary, data=payload)

if serializer.is_valid():

serializer.save()

if request.FILES.get("avatar", None):

user = User.objects.get(id=beneciary.user.id)

user.avatar = upload_file_url

user.save()
83

response = {

"message": "Update successfully.",

"data": serializer.data,

return self.success_response(response)

else:

self.raise_error(

title="Error", message="Invalid data.", errors=serializer.errors

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class UserCheckApplicationStatusAPIView(API):

permission_classes = [IsAuthenticated]

def get(self, request, format=None) -> dict:

try:

has_progress_application = False

applications = AssistanceApplicantForm.objects.filter(

user=request.user

).exclude(application_status__in=["Cancelled", "Disapproved", "Assisted"])

if applications:

has_progress_application = True

response = {

"application_id": applications[0].id if applications else "",

"has_progress_application": has_progress_application,

}
84

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class UserAssistanceApplicantListAPIView(API, Mixins):

permission_classes = [IsAuthenticated]

def get(self, request, format=None) -> dict:

try:

query_params = request.query_params

filters = Q(user=request.user)

if query_params.get("search", None):

filters &= Q(

reference_no__icontains=query_params.get("search", None))

applications = AssistanceApplicantForm.objects.filter(filters)

serializer = AssistanceApplicantFormSerializer(applications, many=True)

response = {"data": serializer.data}

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class UserAssistanceApplicantFormAPIView(API, Mixins):

permission_classes = [IsAuthenticated]

def get_object(self, pk):


85

try:

return AssistanceApplicantForm.objects.get(pk=pk)

except AssistanceApplicantForm.DoesNotExist:

raise Http404

def get(self, request, pk: int, format=None) -> dict:

try:

application = self.get_object(pk)

serializer = AssistanceApplicantFormSerializer(application)

response = {"data": serializer.data}

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

def post(self, request, format=None) -> dict:

try:

payload = request.data

payload["user"] = request.user.id

application_form_length = AssistanceApplicantForm.objects.all().count()

payload[

"reference_no"

] = f"{datetime.datetime.now().strftime('%m%d%y')}
{str(application_form_length + 1).zfill(7)}"

if not request.FILES.get("certificate_of_indigency", None):

self.raise_error(

title="Error",

message="Required barangay certificate of indigency.",

errors=serializer.errors,

if not request.FILES.get("valid_id", None):


86

self.raise_error(

title="Error",

message="Required valid id.",

errors=serializer.errors,

timestamp = int(datetime.datetime.today().timestamp())

uploaded_file = request.FILES["certificate_of_indigency"]

uploaded_file2 = request.FILES["valid_id"]

location = f"{settings.MEDIA_ROOT}/attachments"

base_url = "attachments"

name, extension, upload_file_url = self.custom_upload_file(

uploaded_file, location, base_url, timestamp

name2, extension2, upload_file_url2 = self.custom_upload_file(

uploaded_file2, location, base_url, timestamp

payload["attachment"] = json.dumps({

"certificate_of_indigency": upload_file_url,

"valid_id": upload_file_url2,

})

serializer = AssistanceApplicantFormSerializer(data=payload)

if serializer.is_valid():

serializer.save()

response = {

"message": "Apply successfully.",

return self.success_response(response)

else:

self.raise_error(
87

title="Error", message="Invalid data.", errors=serializer.errors

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

def put(self, request, pk: int, format=None) -> dict:

try:

payload = request.data

payload["user"] = request.user.id

application = self.get_object(pk)

serializer = AssistanceApplicantFormSerializer(application, data=payload)

if serializer.is_valid():

serializer.save()

response = {

"message": "Update successfully.",

return self.success_response(response)

else:

self.raise_error(

title="Error", message="Invalid data.", errors=serializer.errors

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

def patch(self, request, pk: int, format=None) -> dict:

try:

application = self.get_object(pk)

application.set_application_cancelled()

if application.application_status == "Cancelled":
88

response = {"message": "Cancel successfully."}

return self.success_response(response)

else:

self.raise_error(title="Error", message="Unable to cancelled.")

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class UserAnnouncementListAPIView(API):

permission_classes = [IsAuthenticated]

def get(self, request, format=None) -> dict:

try:

announcements = Announcements.objects.all()

serializer = AnnouncementsSerializer(announcements, many=True)

response = {"data": serializer.data}

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class UserAnnouncementFormAPIView(API):

permission_classes = [IsAuthenticated]

def get_object(self, pk):

try:

return Announcements.objects.get(pk=pk)

except Announcements.DoesNotExist:

raise Http404
89

def get(self, request, pk: int, format=None) -> dict:

try:

announcement = self.get_object(pk)

announcement.add_viewers()

serializer = AnnouncementsSerializer(announcement)

response = {"data": serializer.data}

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class AdminLoginAPIView(API, Mixins):

def post(self, request, format=None) -> dict:

try:

payload = request.data

try:

user_account = User.objects.get(Q(email=payload["email"]))

except User.DoesNotExist:

self.raise_error(title="Error", message="Invalid username or


password.")

user = authenticate(

system_id=user_account.system_id, password=payload["password"]

if user != None:

login(request, user)

token, created = Token.objects.get_or_create(user=user)

response = {

"message": "Signin successfully.",

"data": {"token": str(token)},

return self.success_response(response)

else:
90

self.raise_error(title="Error", message="Invalid username or


password.")

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class AdminDashboardDataAPIView(API):

permission_classes = [IsAuthenticated]

def get(self, request, format=None) -> dict:

try:

announcements = Announcements.objects.all()

serializer = AnnouncementsSerializer(announcements, many=True)

applications_status = {

"Financial Assistance": 0,

"Disaster and Calamity Assistance": 0,

"Senior Citizen": 0,

"Children conflict with the law and Child at risk": 0,

"Abuse": 0,

appointments = []

not_review_applications = AssistanceApplicantForm.objects.filter(

application_status=None

for application in not_review_applications:

if (

not application.application_status

and "Financial Assistance"

in application.assessment["client_category"]

):

applications_status["Financial Assistance"] += 1
91

if (

not application.application_status

and "Disaster and Calamity Assistance"

in application.assessment["client_category"]

):

applications_status["Disaster and Calamity Assistance"] += 1

if (

not application.application_status

and "Senior Citizen" in application.assessment["client_category"]

):

applications_status["Senior Citizen"] += 1

if (

not application.application_status

and "Children conflict with the law and Child at risk"

in application.assessment["client_category"]

):

applications_status["Children conflict with the law and Child at


risk"] += 1

if (

not application.application_status

and "Abuse"

in application.assessment["client_category"]

):

applications_status["Abuse"] += 1

date_today = datetime.datetime.now().date()

todays_appointment = AssistanceApplicantForm.objects.filter(

application_status__in=["For Interview", "Approved"]

for application in todays_appointment:

if (
92

application.application_status == "For Interview"

and application.interview_schedule_date.date() == date_today

):

appointments.append(

application.get_interview_appoinment_data_dict()

response = {

"recent_announcements": serializer.data,

"not_review_applicants": applications_status,

"todays_appoinments": sorted(appointments, key=itemgetter("date")),

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class AdminAppointmentsListAPIView(API):

permission_classes = [IsAuthenticated]

def get(self, request, format=None) -> dict:

try:

appointments = []

todays_appointment = AssistanceApplicantForm.objects.filter(

application_status__in=["For Interview", "Approved"]

for application in todays_appointment:

if application.application_status == "For Interview":

appointments.append(

application.get_interview_appoinment_data_dict()

)
93

response = {

"appoinments": sorted(appointments, key=itemgetter("date")),

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class AdminAssistanceApplicantListAllAPIView(API, Mixins):

permission_classes = [IsAuthenticated]

def get(self, request, format=None) -> dict:

try:

query_params = request.query_params

filters = Q(application_status__icontains="Assisted")

if query_params.get("search", None):

filters &= Q(reference_no__icontains=query_params.get("search", None))

if not query_params.get("case", None) == "all":

filters &=
Q(assessment__client_category__icontains=query_params.get("case", None).replace("-", "
"))

if not query_params.get("assistance", None) == "all":

filters &=
Q(assessment__sub_client_category__icontains=query_params.get("assistance", None))

if not query_params.get("beneficiary", None) == "all":

filters &= Q(user__system_id=query_params.get("beneficiary", None))


94

applications = AssistanceApplicantForm.objects.select_related(

"user"

).filter(filters)

data = [application.get_table_dict() for application in applications]

response = {"data": data}

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class AdminAssistanceApplicantFormAllAPIView(API, Mixins):

def get_object(self, pk):

try:

return AssistanceApplicantForm.objects.get(reference_no__icontains=pk)

except AssistanceApplicantForm.DoesNotExist:

raise Http404

def get(self, request, pk: int, format=None) -> dict:

try:

application = self.get_object(pk)

if not application.application_status:

application.set_application_viewed()

data = application.get_form_data_dict()

response = {"data": data}

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:


95

return self.server_error_response(exc)

class AdminAssistanceApplicantListAPIView(API, Mixins):

permission_classes = [IsAuthenticated]

def get(self, request, slug, format=None) -> dict:

try:

filtered_slug = slug.replace("-", " ")

query_params = request.query_params

filters = Q(assessment__client_category__icontains=filtered_slug)

if query_params.get("search", None):

filters &= Q(

reference_no__icontains=query_params.get("search", None)

) | Q(user__system_id__icontains=query_params.get("search", None))

if query_params.get("type", None) == "not-yet-review":

filters &= Q(application_status=None)

if query_params.get("type", None) == "cancelled":

filters &= Q(application_status__icontains="Cancelled")

if query_params.get("type", None) == "disapproved":

filters &= Q(application_status__icontains="Disapproved")

if query_params.get("type", None) == "viewed":

filters &= Q(application_status__icontains="Viewed")

if query_params.get("type", None) == "interview":

filters &= Q(application_status__icontains="For Interview")

if query_params.get("type", None) == "interviewed":

filters &= Q(application_status__icontains="Interviewed")

if query_params.get("type", None) == "for_release":

filters &= Q(application_status__icontains="Approved")

if query_params.get("type", None) == "assisted":


96

filters &= Q(application_status__icontains="Assisted")

if not query_params.get("assistance", None) == "all":

filters &=
Q(assessment__sub_client_category__icontains=query_params.get("assistance", None))

applications = AssistanceApplicantForm.objects.select_related(

"user"

).filter(filters)

data = [application.get_table_dict() for application in applications]

response = {"data": data}

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class AdminAssistanceApplicantFormAPIView(API, Mixins):

permission_classes = [IsAuthenticated]

def get_object(self, pk):

try:

return AssistanceApplicantForm.objects.get(reference_no__icontains=pk)

except AssistanceApplicantForm.DoesNotExist:

raise Http404

def get(self, request, slug: str, pk: int, format=None) -> dict:

try:

application = self.get_object(pk)

if not application.application_status:

application.set_application_viewed()
97

data = application.get_form_data_dict()

response = {"data": data}

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

def patch(self, request, slug: str, pk: int, format=None) -> dict:

try:

payload = request.data

try:

application = AssistanceApplicantForm.objects.get(id=pk)

except AssistanceApplicantForm.DoesNotExist:

raise Http404

if payload.get("action_type", None) == "disapprove":

application.set_application_disapproved()

if payload.get("action_type", None) == "interview":

if not payload["interview_schedule_date"]:

self.raise_error(title="Error", message="Date is required.")

schedule_date = payload["interview_schedule_date_text"]

self.send_schedule_sms(self.filter_mobile_number(application.user.mobile_number),
f"Your request application is approved. You are now schedule for an interview this
{schedule_date}. Please visit the nearest MSWD office")

application.set_application_for_interview(request)

if payload.get("action_type", None) == "interviewed":

application.set_application_interviewed(request)

if payload.get("action_type", None) == "approve":

self.send_schedule_sms(self.filter_mobile_number(application.user.mobile_number),
98

"Your request assistance is approved. Please visit the nearest MSWD office to claim
your cash assistance.")

application.set_application_approved(request)

if payload.get("action_type", None) == "release":

if not request.FILES.get("proof", None):

self.raise_error(

title="Error",

message="Proof of received assistance is required."

timestamp = int(datetime.datetime.today().timestamp())

uploaded_file = request.FILES["proof"]

location = f"{settings.MEDIA_ROOT}/proofs"

base_url = "proofs"

name, extension, upload_file_url = self.custom_upload_file(

uploaded_file, location, base_url, timestamp

print(upload_file_url)

payload["proof"] = upload_file_url

if not payload["assistance"]:

self.raise_error(title="Error", message="Assistance is required.")

if not payload["remarks"]:

self.raise_error(title="Error", message="Remarks is required.")

application.assistance = payload["assistance"]

application.cash = payload["cash"]

application.remarks = payload["remarks"]

application.proof = payload["proof"]

application.save()

application.set_application_claimed(request)

response = {"data": application.get_form_data_dict()}


99

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class AdminBeneficiaryListAPIView(API, Mixins):

permission_classes = [IsAuthenticated]

def get(self, request, format=None) -> dict:

try:

query_params = request.query_params

filters = Q(user__is_superadmin=False, user__is_admin=False)

if query_params.get("search", None):

filters &= (

Q(firstname__icontains=query_params.get("search", None))

| Q(middlename__icontains=query_params.get("search", None))

| Q(lastname__icontains=query_params.get("search", None))

| Q(extension__icontains=query_params.get("search", None))

| Q(user__mobile_number__icontains=query_params.get("search",
None))

| Q(user__system_id__icontains=query_params.get("search", None))

users = BeneficiaryProfile.objects.filter(filters)

data = [user.get_table_dict() for user in users]

response = {"data": data}

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:


100

return self.server_error_response(exc)

class AdminBeneficiaryFormAPIView(API, Mixins):

permission_classes = [IsAuthenticated]

def get_object(self, slug):

try:

return BeneficiaryProfile.objects.get(user__system_id=slug)

except BeneficiaryProfile.DoesNotExist:

raise Http404

def get(self, request, slug: str, format=None) -> dict:

try:

beneficiarys = self.get_object(slug)

data = beneficiarys.get_form_data_dict()

response = {"data": data}

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class AdminAnnouncementListAPIView(API):

permission_classes = [IsAuthenticated]

def get(self, request, format=None) -> dict:

try:

query_params = request.query_params

filters = Q()
101

if query_params.get("search", None):

filters &= Q(title__icontains=query_params.get("search", None))

announcements = Announcements.objects.filter(filters)

serializer = AnnouncementsSerializer(announcements, many=True)

response = {"data": serializer.data}

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class AdminAnnouncementFormAPIView(API, Mixins):

permission_classes = [IsAuthenticated]

def get_object(self, pk):

try:

return Announcements.objects.get(pk=pk)

except Announcements.DoesNotExist:

raise Http404

def get(self, request, pk: int, format=None) -> dict:

try:

announcement = self.get_object(pk)

serializer = AnnouncementsSerializer(announcement)

response = {"data": serializer.data}

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)
102

def post(self, request, format=None) -> dict:

try:

payload = request.data

if not request.FILES.get("banner", None):

self.raise_error(

title="Error", message="Banner is required."

timestamp = int(datetime.datetime.today().timestamp())

uploaded_file = request.FILES["banner"]

location = f"{settings.MEDIA_ROOT}/announcements"

base_url = "announcements"

name, extension, upload_file_url = self.custom_upload_file(

uploaded_file, location, base_url, timestamp

payload["banner"] = upload_file_url

users = User.objects.all()

bulk_recipient = ",".join([user.mobile_number for user in users])

serializer = AnnouncementsSerializer(data=payload)

if serializer.is_valid():

serializer.save()

response = {

"message": "Saved successfully.",

self.send_bulk_sms(bulk_recipient, "MSWD Jasaan has release some


latest announcements, Check it out now on your mobile device!")

return self.success_response(response)

else:

self.raise_error(title="Error", message=serializer.errors)

except HumanReadableError as exc:


103

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

def put(self, request, pk: int, format=None) -> dict:

try:

payload = request.data

announcement = self.get_object(pk)

if request.FILES.get("banner", None):

timestamp = int(datetime.datetime.today().timestamp())

uploaded_file = request.FILES["banner"]

location = f"{settings.MEDIA_ROOT}/announcements"

base_url = "announcements"

name, extension, upload_file_url = self.custom_upload_file(

uploaded_file, location, base_url, timestamp

payload["banner"] = upload_file_url

serializer = AnnouncementsSerializer(announcement, data=payload)

if serializer.is_valid():

serializer.save()

response = {

"message": "Update successfully.",

return self.success_response(response)

else:

self.raise_error(

title="Error", message="Invalid data.", errors=serializer.errors

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)


104

except Exception as exc:

return self.server_error_response(exc)

def delete(self, request, pk: int, format=None) -> dict:

try:

announcement = self.get_object(pk)

announcement.delete()

response = {

"message": "Delete successfully.",

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

class AdminChartReportAPIView(API):

permission_classes = [IsAuthenticated]

def get(self, request, format=None) -> dict:

try:

applications_status = {

"Financial Assistance": 0,

"Disaster and Calamity Assistance": 0,

"Senior Citizen": 0,

"Children conflict with the law and Child at risk": 0,

"Abuse": 0,

assisted_applications = AssistanceApplicantForm.objects.filter(

application_status__icontains="Assisted"

for application in assisted_applications:


105

if (

application.application_status == "Assisted"

and "Financial Assistance"

in application.assessment["client_category"]

):

applications_status["Financial Assistance"] += 1

if (

application.application_status == "Assisted"

and "Disaster and Calamity Assistance"

in application.assessment["client_category"]

):

applications_status["Disaster and Calamity Assistance"] += 1

if (

application.application_status == "Assisted"

and "Senior Citizen" in application.assessment["client_category"]

):

applications_status["Senior Citizen"] += 1

if (

application.application_status == "Assisted"

and "Children conflict with the law and Child at risk"

in application.assessment["client_category"]

):

applications_status["Children conflict with the law and Child at


risk"] += 1

if (

application.application_status == "Assisted"

and "Abuse"

in application.assessment["client_category"]

):

applications_status["Abuse"] += 1
106

response = {

"assisted_applicants": applications_status,

return self.success_response(response)

except HumanReadableError as exc:

return self.error_response(exc, self.error_dict, self.status)

except Exception as exc:

return self.server_error_response(exc)

Announcement

<template>

<div>

<div class="input-group mb-3">

<input

type="text"

class="form-control"

placeholder="Search title"

v-model="filters.search"

@keyup.enter="getAnnouncements()"

/>

<button

class="btn btn-outline-secondary"

type="button"

@click="clearSearch()"

>

Clear

</button>

<button

class="btn btn-outline-secondary"

type="button"

id="button-addon2"

@click="getAnnouncements()"

>
107

Search

</button>

</div>

<div class="float-right mb-3">

<button

class="btn btn-primary"

@click="toggleCreateEditAnnouncementModal('create')"

>

Create

</button>

</div>

<div>

<div

class="row ibox"

v-for="announcement in announcements"

v-bind:key="announcement.id"

@click.prevent="showAnnouncementsModal(announcement.id)"

>

<div

class="col-3 ibox-content text-center announcement-banner"

:style="`background: url(${announcement.banner})`"

></div>

<div class="col-9 ibox-content" style="width: 100% !important">

<h2>

<strong>{{ announcement.title }}</strong>

</h2>

<div class="small m-b-xs">

<strong>{{ capitalize(announcement.author) }}</strong

>&nbsp;

<span class="text-muted"

><i class="fa fa-clock-o"></i>

{{ new Date(announcement.created_at).toLocaleString("en-US") }}

</span>
108

</div>

<div class="description">

{{ hyperlink(announcement.description, announcement.id) }}

<div :id="`desc${announcement.id}`"></div>

<div class="fade-away"></div>

</div>

<div class="row">

<div class="col-md-6"></div>

<div class="col-md-6">

<div class="text-right">

<i class="fa fa-eye"> </i> {{ announcement.viewers }} views

</div>

</div>

</div>

</div>

</div>

</div>

<!-- Create/Edit Announcement Modal -->

<div

class="modal fade"

id="announcementModal"

data-bs-backdrop="static"

tabindex="-1"

aria-labelledby="exampleModalLabel"

aria-hidden="true"

>

<div class="modal-dialog modal-xl">

<div class="modal-content">

<div class="modal-header">

<h3 class="modal-title fs-5" id="exampleModalLabel"></h3>

<button type="button" class="close" data-dismiss="modal">

<span aria-hidden="true">&times;</span

><span class="sr-only">Close</span>
109

</button>

</div>

<div class="modal-body">

<div>

<div class="banner-upload">

<div class="banner-edit">

<input

type="file"

id="banner"

accept="image/*"

@change="readURL($event)"

/>

<label for="banner">

<div class="text-center mt-1">

<i class="fas fa-pencil-alt"></i>

</div>

</label>

</div>

<div class="banner-preview">

<div id="bannerPreview"></div>

</div>

</div>

</div>

<div>

<div class="form-group">

<label for="author">Author</label>

<input

type="text"

class="form-control"

id="author"

v-model="selectedForm.author"

/>

</div>
110

<div class="form-group">

<label for="title">Title</label>

<input

type="text"

class="form-control"

id="title"

v-model="selectedForm.title"

/>

</div>

<div class="form-group">

<label for="description">Description</label>

<textarea

class="form-control"

rows="8"

id="description"

v-model="selectedForm.description"

/>

</div>

</div>

</div>

<div class="modal-footer">

<button

type="button"

class="btn btn-success"

@click="createAnnouncements()"

v-if="!selectedForm.id"

>

Save

</button>

<button

type="button"

class="btn btn-danger"

@click="deleteAnnouncement()"
111

v-if="selectedForm.id"

>

Delete

</button>

<button

type="button"

class="btn btn-success"

@click="updateAnnouncement()"

v-if="selectedForm.id"

>

Save

</button>

<button

type="button"

class="btn btn-secondary"

data-dismiss="modal"

>

Close

</button>

</div>

</div>

</div>

</div>

<!-- Create/Edit Announcement Modal -->

</div>

</template>

<script>

import axios from "axios";

import { useToast } from "vue-toastification";

import intialData from "../intialData";


112

const serverSideUrlApi = intialData.serverSideUrlApi;

export default {

setup() {

const toast = useToast();

return { toast };

},

data() {

return {

announcements: [],

selectedForm: {

banner: "",

author: "",

title: "",

description: "",

},

filters: {

search: "",

},

};

},

created() {

this.getAnnouncements();

},

methods: {

readURL(event) {

let reader = new FileReader();

reader.readAsDataURL(event.target.files[0]);

reader.onload = (input) => {

const image = new Image();

image.src = input.target.result;

image.onload = () => {

this.selectedForm.banner = document.getElementById("banner").files[0];
113

document.getElementById("bannerPreview").style.backgroundImage =

"url(" + input.target.result + ")";

};

};

},

async getAnnouncements() {

try {

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(

`${serverSideUrlApi}/admin-announcements/?search=${this.filters.search}`,

headers

);

this.announcements = response.data.data;

} catch (error) {

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";


114

} else {

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

},

async createAnnouncements() {

try {

let data = new FormData();

if (typeof this.selectedForm.banner === "object") {

data.append("banner", this.selectedForm.banner);

data.append("author", this.selectedForm.author);

data.append("title", this.selectedForm.title);

data.append("description", this.selectedForm.description);

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.post(

`${serverSideUrlApi}/admin-announcement/`,

data,

headers

);

this.toast.success(response.data.message);

this.getAnnouncements();

this.toggleCreateEditAnnouncementModal();

} catch (error) {

console.error(error);

let message = "";


115

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

} else {

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

},

async showAnnouncementsModal(id) {

try {

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(

`${serverSideUrlApi}/admin-announcement/${id}`,

headers

);

this.selectedForm = response.data.data;
116

if (this.selectedForm.banner) {

document.getElementById("bannerPreview").style.backgroundImage =

"url(" + this.selectedForm.banner.replace(/ /g, "%20") + ")";

this.toggleCreateEditAnnouncementModal();

} catch (error) {

console.error(error);

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

} else {

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

},

async updateAnnouncement() {

try {

let data = new FormData();

if (typeof this.selectedForm.banner === "object") {


117

data.append("banner", this.selectedForm.banner);

data.append("author", this.selectedForm.author);

data.append("title", this.selectedForm.title);

data.append("description", this.selectedForm.description);

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.put(

`${serverSideUrlApi}/admin-announcement/${this.selectedForm.id}/`,

data,

headers

);

this.toast.success(response.data.message);

this.getAnnouncements();

this.toggleCreateEditAnnouncementModal();

} catch (error) {

console.error(error);

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);
118

} else {

message = "Something went wrong, Please contact the administrator.";

} else {

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

},

async deleteAnnouncement() {

try {

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.delete(

`${serverSideUrlApi}/admin-announcement/${this.selectedForm.id}/`,

headers

);

this.toast.success(response.data.message);

this.getAnnouncements();

this.toggleCreateEditAnnouncementModal();

} catch (error) {

console.error(error);

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {
119

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

} else {

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

},

clearSearch() {

this.filters.search = "";

this.getBeneficiaries();

},

toggleCreateEditAnnouncementModal(type) {

if (type === "create") {

this.selectedForm = {};

document.getElementById("bannerPreview").style.backgroundImage = "";

$("#announcementModal").modal("toggle");

},

capitalize(text) {

return text ? text.charAt(0).toUpperCase() + text.slice(1) : text;

},

hyperlink(textContent, id) {

let newTextContent = textContent.replace(

/(https?:\/\/[^\s]+)/g,

(href) =>
120

`<a href="${href}" target="_blank" style="position: relative;z-index:


999;">${href}</a>`

);

let doc = new DOMParser().parseFromString(

`<span>${newTextContent}</span>`,

"text/xml"

);

let newDiv = document.createElement("div");

newDiv.innerHTML = doc.firstChild.innerHTML;

setTimeout(() => {

let divDesc = document.querySelector(`#desc${id}`);

if (!divDesc.hasChildNodes()) {

divDesc.appendChild(newDiv);

} else {

while (divDesc.firstChild) {

divDesc.removeChild(divDesc.firstChild);

divDesc.appendChild(newDiv);

}, 100);

},

},

};

</script>

<style scoped>

.banner-upload {

position: relative;

margin: 0 0 10px 0;

.banner-upload .banner-edit {

position: absolute;

right: 12px;

z-index: 1;
121

top: 10px;

.banner-upload .banner-edit input {

display: none !important;

.banner-upload .banner-edit input + label {

display: inline-block;

width: 34px;

height: 34px;

margin-bottom: 0;

border-radius: 2px;

background: #ffffff;

border: 1px solid transparent;

box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.12);

cursor: pointer;

font-weight: normal;

transition: all 0.2s ease-in-out;

.banner-upload .banner-edit input + label:hover {

background: #f1f1f1;

border-color: #d6d6d6;

.banner-upload .banner-preview {

width: 100%;

height: 450px;

position: relative;

border-radius: 2px;

border: 3px solid #f8f8f8;

box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);

background: black;

.banner-upload .banner-preview > div {

width: 100%;
122

height: 100%;

border-radius: 2px;

background-size: contain;

background-repeat: no-repeat;

background-position: center;

.description {

position: relative;

overflow: hidden;

height: 135px;

white-space: break-spaces;

display: flex;

.fade-away {

height: 100px;

position: absolute;

background: linear-gradient(to bottom, transparent, white);

bottom: 0;

width: 100%;

.announcement-banner {

background-repeat: no-repeat !important;

background-size: contain !important;

background-position: center !important;

background-color: black !important;

</style>

Appointment

<template>

<main>

<div class="w-50">
123

<FullCalendar :options="calendarOptions" />

</div>

</main>

</template>

<script>

import axios from "axios";

import { useToast } from "vue-toastification";

import FullCalendar from "@fullcalendar/vue3";

import dayGridPlugin from "@fullcalendar/daygrid";

import interactionPlugin from "@fullcalendar/interaction";

import intialData from "../intialData";

const serverSideUrlApi = intialData.serverSideUrlApi;

import "@fullcalendar/core/vdom";

export default {

components: {

FullCalendar,

},

setup() {

const toast = useToast();

return { toast };

},

data() {
124

return {

appoinments: [],

calendarOptions: {

selectable:true,

plugins: [dayGridPlugin, interactionPlugin],

initialView: "dayGridMonth",

eventClick: this.handleSelect,

events: [],

},

};

},

created() {

this.getAppoinments();

},

methods: {

async getAppoinments() {

try {

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(

`${serverSideUrlApi}/admin-appoinments/`,

headers

);

this.appoinments = response.data.appoinments;
125

this.appoinments.forEach(element => {

this.calendarOptions.events.push({

reference_no: element.reference_no,

title: element.application_status === 'Approved' ? `For release assistance


with ${element.name}` : `For interview with ${element.name}`,

date: new Date(element.date)

})

});

} catch (error) {

console.log(error)

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

} else {
126

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

},

handleSelect(arg) {

this.gotoToApplication(arg.event._def.extendedProps.reference_no);

},

gotoToApplication(reference_no) {

let appointment = this.appoinments.find(element => element.reference_no ===


reference_no);

let path = (appointment.assessment.client_category).replaceAll(" ", "-");

this.$router.push({ path: `/assistances/${path}`, query: { id:


reference_no } });

},

},

};

</script>

<style scoped></style>

Assistance View

<template>

<div>

<div class="input-group mb-3">

<input

type="text"

class="form-control"

placeholder="Ref ID only"
127

v-model="filters.search"

@keyup.enter="getAssistanceApplications()"

/>

<button

class="btn btn-outline-secondary"

type="button"

@click="clearSearch()"

>

Clear

</button>

<button

class="btn btn-outline-secondary"

type="button"

id="button-addon2"

@click="getAssistanceApplications()"

>

Search

</button>

</div>

<div class="d-flex mb-4">

<div class="form-group w-25">

<label for="inputSelect">Status</label>

<select

id="inputSelect"

class="form-control"

v-model="filters.type"

@change="getAssistanceApplications()"
128

>

<option value="all" selected>All</option>

<option value="not-yet-review">Not yet Review</option>

<option value="cancelled">Cancelled</option>

<option value="disapproved">Disapproved</option>

<option value="reviewing">Reviewed</option>

<option value="interview">For Interview</option>

<option value="interviewed">Interviewed</option>

<option value="for_release">Approved for release</option>

<option value="assisted">Assisted</option>

</select>

</div>

<div class="form-group w-25 ml-3">

<label for="inputSelect">Assistance</label>

<select

id="inputSelect"

class="form-control"

v-model="filters.assistance"

@change="getAssistanceApplications()"

>

<option value="all" selected>All</option>

<option

:value="subClient"

v-for="(subClient, index) in selectedSubClientCategoryList"

v-bind:key="index"

>

{{ subClient }}
129

</option>

</select>

</div>

</div>

<table class="table table-bordered">

<thead>

<tr>

<th>#</th>

<th scope="col">Ref ID</th>

<th scope="col" colspan="2">Case</th>

<th scope="col">Beneficiary ID</th>

<th scope="col">Beneficiary Name</th>

<th scope="col">Status</th>

<!-- <th scope="col">Created at</th>

<th scope="col">Last changes</th> -->

</tr>

</thead>

<tbody v-if="applications.length">

<tr

v-for="(application, index) in applications"

v-bind:key="application.id"

@click.prevent="showApplicationModalForm(application.reference_no)"

>

<td>{{ index + 1 }}</td>

<td>{{ application.reference_no }}</td>

<td>

{{ application.assessment.client_category }}
130

</td>

<td>

{{ application.assessment.sub_client_category }}

</td>

<td>

{{ application.user }}

<button

class="btn btn-sm btn-primary"

@click.stop="gotoToUser(application.user)"

>

Redirect

</button>

</td>

<td>{{ application.name }}</td>

<td>

<span v-if="application.application_status">

{{ application.application_status }}

</span>

<span v-if="!application.application_status"> Not yet Review </span>

</td>

<!-- <td>

{{ new Date(application.created_at).toLocaleString("en-US") }}

</td>

<td>

{{ new Date(application.updated_at).toLocaleString("en-US") }}

</td> -->

</tr>
131

</tbody>

<tbody v-if="!applications.length">

<tr>

<td colspan="100%" class="text-center">No application found!</td>

</tr>

</tbody>

</table>

<!-- Application Form Modal -->

<div

class="modal fade"

id="exampleModal"

data-bs-backdrop="static"

tabindex="-1"

aria-labelledby="exampleModalLabel"

aria-hidden="true"

>

<div class="modal-dialog modal-xl">

<div class="modal-content" v-if="Object.keys(this.selectedForm).length">

<div class="modal-header">

<h3 class="modal-title fs-5" id="exampleModalLabel">

{{ selectedForm.assessment.client_category }} -

{{ selectedForm.reference_no }}

</h3>

<button type="button" class="close" data-dismiss="modal">

<span aria-hidden="true">&times;</span

><span class="sr-only">Close</span>

</button>
132

</div>

<div class="modal-body">

<div class="text-center mb-4">

<h3>Application Details</h3>

</div>

<div class="row g-3">

<div class="col-3">

<div class="text-center mb-5">

<img

:src="`${selectedForm.avatar}`"

width="200"

alt="avatar"

/>

</div>

</div>

<div class="col-9">

<div class="row g-3">

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Name</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="checkIfDataIsNone(selectedForm.name)"

readonly
133

/>

</div>

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Sex</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="checkIfDataIsNone(selectedForm.sex)"

readonly

/>

</div>

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Age</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="checkIfDataIsNone(selectedForm.age)"

readonly

/>

</div>

<div class="col-4 form-group">


134

<label for="validationDefault01" class="form-label"

>Mobile Number</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(selectedForm.mobile_number)

"

readonly

/>

</div>

<div class="col-8 application-status">

<span v-if="selectedForm.application_status">

{{ selectedForm.application_status }}

</span>

<span v-if="!selectedForm.application_status">

Not yet Review

</span>

</div>

</div>

</div>

<div class="col-6 form-group">

<label for="validationDefault01" class="form-label"

>Inverview Schedule</label

>
135

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(selectedForm.interview_schedule_date) !==

'N/A'

? new Date(

selectedForm.interview_schedule_date

).toLocaleString('en-US')

: 'N/A'

"

readonly

/>

</div>

<div class="col-6 form-group">

<label for="validationDefault01" class="form-label"

>Release Schedule</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(selectedForm.release_schedule_date) !==

'N/A'

? new Date(
136

selectedForm.release_schedule_date

).toLocaleString('en-US')

: 'N/A'

"

readonly

/>

</div>

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Interviewed By:</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="checkIfDataIsNone(selectedForm.interviewed_by)"

readonly

/>

</div>

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Approved By:</label

>

<input

type="text"

class="form-control"

id="validationDefault01"
137

v-bind:value="checkIfDataIsNone(selectedForm.approved_by)"

readonly

/>

</div>

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Released By:</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="checkIfDataIsNone(selectedForm.released_by)"

readonly

/>

</div>

</div>

<div class="text-center mt-3 mb-4">

<h3>Client Identify Information</h3>

</div>

<div class="row g-3">

<div class="col-3 form-group">

<label for="validationDefault01" class="form-label"

>Lastname</label

>

<input

type="text"
138

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information.lastname

"

readonly

/>

</div>

<div class="col-3 form-group">

<label for="validationDefault01" class="form-label"

>Firstname</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information.firstname

"

readonly

/>

</div>

<div class="col-3 form-group">


139

<label for="validationDefault01" class="form-label"

>Middlename</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information.middlename

"

readonly

/>

</div>

<div class="col-3 form-group">

<label for="validationDefault01" class="form-label"

>Ext(Jr, Sr)</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information.extension

)
140

"

readonly

/>

</div>

<div class="col-3 form-group">

<label for="validationDefault01" class="form-label">Sex</label>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information.sex

"

readonly

/>

</div>

<div class="col-3 form-group">

<label for="validationDefault01" class="form-label"

>Date of Birth</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="
141

checkIfDataIsNone(

selectedForm.client_identifying_information.date_of_birth

"

readonly

/>

</div>

<div class="col-6 form-group">

<label for="validationDefault01" class="form-label"

>Place of Birth</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information.place_of_birth

"

readonly

/>

</div>

<div class="col-3 form-group">

<label for="validationDefault01" class="form-label"

>Relationship to Beneficiary</label

>
142

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information

.relationship_to_beneficiary

"

readonly

/>

</div>

<div class="col-2 form-group">

<label for="validationDefault01" class="form-label"

>Civil Status</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information.civil_status

"

readonly
143

/>

</div>

<div class="col-3 form-group">

<label for="validationDefault01" class="form-label"

>Religion</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information.religion

"

readonly

/>

</div>

<div class="col-3 form-group">

<label for="validationDefault01" class="form-label"

>Nationality</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="
144

checkIfDataIsNone(

selectedForm.client_identifying_information.nationality

"

readonly

/>

</div>

<div class="col-6 form-group">

<label for="validationDefault01" class="form-label"

>Highest Educational Attainment</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information

.highest_educational_attainment

"

readonly

/>

</div>

<div class="col-6 form-group">

<label for="validationDefault01" class="form-label"

>Skills/Occupation</label
145

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information

.skills_or_occupation

"

readonly

/>

</div>

<div class="col-6 form-group">

<label for="validationDefault01" class="form-label"

>Estimated Monthly Income</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information

.estimated_monthly_income

)
146

"

readonly

/>

</div>

<div class="col-6"></div>

<div class="col-2 form-group">

<label for="validationDefault01" class="form-label"

>Region</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information.region

"

readonly

/>

</div>

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Province</label

>

<input

type="text"
147

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information.province

"

readonly

/>

</div>

<div class="col-6 form-group">

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information

.city_or_municipality

"

readonly

/>

<label for="validationDefault01" class="form-label"

>City/Municipality</label

>

</div>
148

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>District</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information.district

"

readonly

/>

</div>

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Barangay</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information.barangay
149

"

readonly

/>

</div>

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Street/Purok</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information

.no_street_or_purok

"

readonly

/>

</div>

</div>

<div class="text-center mt-3 mb-4">

<h3>Beneficiary's Family Composition</h3>

</div>

<div class="row">
150

<table class="table">

<thead>

<tr>

<th>Lastname</th>

<th>Firstname</th>

<th>Middlename</th>

<th>Sex</th>

<th>Birthdate</th>

<th>Civil Status</th>

<th>Relationship</th>

<th>Highest Educational Attainment</th>

<th>Skills/Occupation</th>

<th>Estimated Monthly Income</th>

</tr>

</thead>

<tbody>

<tr

v-for="(

member, index

) in selectedForm.beneficiarys_family_composition"

v-bind:key="index"

>

<td>{{ member.lastname }}</td>

<td>{{ member.firstname }}</td>

<td>{{ member.middlename }}</td>

<td>{{ member.sex }}</td>

<td>{{ member.date_of_birth }}</td>


151

<td>{{ member.civil_status }}</td>

<td>{{ member.relationship }}</td>

<td>{{ member.highest_educational_attainment }}</td>

<td>{{ member.skills_or_occupation }}</td>

<td>{{ member.estimated_monthly_income }}</td>

</tr>

</tbody>

</table>

</div>

<div class="text-center mt-3 mb-4">

<h3>Assesment</h3>

</div>

<div class="row g-3">

<div class="col-6 form-group">

<label for="floatingTextarea2">Problem/s Presented</label>

<textarea

class="form-control"

placeholder="Leave a comment here"

id="floatingTextarea2"

style="height: 100px"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information

.problems_presented

"

readonly
152

></textarea>

</div>

<div class="col-6 form-group">

<label for="floatingTextarea2"

>Social Worker's Assessment</label

>

<textarea

class="form-control"

placeholder="Leave a comment here"

id="floatingTextarea2"

style="height: 100px"

v-bind:value="

checkIfDataIsNone(

selectedForm.client_identifying_information

.social_workers_assessment

"

readonly

></textarea>

</div>

<div class="col-6 form-group">

<label for="validationDefault01" class="form-label"

>Client Category</label

>

<input

type="text"

class="form-control"
153

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(selectedForm.assessment.client_category)

"

readonly

/>

</div>

<div class="col-6 form-group">

<label for="validationDefault01" class="form-label"

>Client Sub-Category</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

selectedForm.assessment.sub_client_category

"

readonly

/>

</div>

</div>

<div class="text-center mt-3 mb-4" v-if="selectedForm.attachment">

<h3>Attachments</h3>

</div>
154

<div v-if="selectedForm.attachment">

<div class="d-flex">

<div class="mr-2">

<label>Barangay Certificate of Indigency</label>

</div>

<div>

<a

class="download-attachment"

:href="selectedForm.attachment.certificate_of_indigency"

target="_blank"

rel="noopener noreferrer"

>View</a

>

</div>

</div>

<div class="d-flex">

<div class="mr-2"><label>Valid ID</label></div>

<div>

<a

class="download-attachment"

:href="selectedForm.attachment.valid_id"

target="_blank"

rel="noopener noreferrer"

>View</a

>

</div>

</div>
155

</div>

</div>

<div class="modal-footer">

<button

v-if="this.selectedForm.application_status !== 'Assisted'"

type="button"

class="btn btn-danger"

@click="changeApplicationProcessStatus('disapprove')"

>

Disapproved Application

</button>

<button

v-if="

!this.selectedForm.application_status ||

this.selectedForm.application_status === 'Reviewed'

"

type="button"

class="btn btn-primary"

@click="toggleSchedulingModal('interview')"

>

Set for Interview

</button>

<button

v-if="this.selectedForm.application_status === 'For Interview'"

type="button"

class="btn btn-primary"

@click="changeApplicationProcessStatus('interviewed')"
156

>

Approve interview

</button>

<button

v-if="this.selectedForm.application_status === 'Interviewed' ||


this.selectedForm.application_status === 'Disapproved'"

type="button"

class="btn btn-primary"

@click="changeApplicationProcessStatus('approve')"

>

Approve Assistance

</button>

<button

v-if="this.selectedForm.application_status === 'Approved'"

type="button"

class="btn btn-primary"

@click="toggleReleasedModal()"

>

Set as Assisted

</button>

<button

type="button"

class="btn btn-secondary"

data-dismiss="modal"

>

Close

</button>
157

</div>

</div>

</div>

</div>

<!-- Application Form Modal -->

<!-- Input Schedule Modal -->

<div

class="modal fade"

id="inputScheduleModal"

tabindex="-2"

aria-labelledby="exampleModalLabel"

aria-hidden="true"

>

<div class="modal-dialog modal-md">

<div class="modal-content">

<div class="modal-body">

<h2 v-if="isInterview">

<b>Select a schedule for interview</b>

</h2>

<h2 v-if="!isInterview">

<b>Select a schedule for release assistance</b>

</h2>

<v-date-picker

mode="dateTime"

:valid-hours="{ min: 8, max: 17 }"

:minute-increment="5"

:min-date="new Date()"
158

:attributes="attributes"

v-model="selectedScheduleDate"

:disabled-dates="{ weekdays: [1, 7] }"

is-expanded

/>

</div>

<div class="modal-footer">

<button

v-if="isInterview"

type="button"

class="btn btn-warning"

@click="changeApplicationProcessStatus('interview')"

>

Submit

</button>

<button

v-if="!isInterview"

type="button"

class="btn btn-warning"

@click="changeApplicationProcessStatus('approve')"

>

Submit

</button>

<button

type="button"

class="btn btn-secondary"

data-dismiss="modal"
159

>

Close

</button>

</div>

</div>

</div>

</div>

<!-- Input Schedule Modal -->

<!-- Released Assistance Modal -->

<div

class="modal fade"

id="inputReleasedModal"

tabindex="-2"

aria-labelledby="exampleModalLabel"

aria-hidden="true"

>

<div class="modal-dialog modal-md">

<div class="modal-content">

<div class="modal-body">

<div>

<label for="">Proof of received assistance</label>

<div class="banner-upload">

<div class="banner-edit">

<input

type="file"

id="banner"

accept="image/*"
160

@change="readURL($event)"

/>

<label for="banner">

<div class="text-center mt-1">

<i class="fas fa-pencil-alt"></i>

</div>

</label>

</div>

<div class="banner-preview">

<div id="bannerPreview"></div>

</div>

</div>

</div>

<div class="form-group">

<div class="i-checks">

<label>

<input

type="radio"

v-model="selectedAssistance"

value="cash"

name="assist_release"

/>

Cash

</label>

</div>

<div class="i-checks">

<label>
161

<input

type="radio"

v-model="selectedAssistance"

value="others"

name="assist_release"

/>

Others

</label>

</div>

</div>

<div class="form-group" v-if="selectedAssistance === 'cash'">

<label for="floatingTextarea2">Cash</label>

<input

class="form-control"

id="floatingTextarea2"

v-model="cash"

placeholder="0"

/>

</div>

<div class="form-group">

<label for="floatingTextarea2">Remarks</label>

<textarea

class="form-control"

id="floatingTextarea2"

style="height: 100px"

v-model="remarks"

></textarea>
162

</div>

</div>

<div class="modal-footer">

<button

type="button"

class="btn btn-warning"

@click="changeApplicationProcessStatus('release')"

>

Submit

</button>

<button

type="button"

class="btn btn-secondary"

data-dismiss="modal"

>

Close

</button>

</div>

</div>

</div>

</div>

<!-- Release Assistance Modal -->

</div>

</template>

<script>

import axios from "axios";


163

import { useToast } from "vue-toastification";

import intialData from "../intialData";

const serverSideUrl = intialData.serverSideUrl;

const serverSideUrlApi = intialData.serverSideUrlApi;

export default {

setup() {

const toast = useToast();

return { toast };

},

data() {

return {

Url: serverSideUrl,

slug: this.$route.params.slug,

subClientCategoryOptions: {

financial: [

"Educational Assistance",

"Death Assistance",

"Medical Assistance",

],

disaster_calamity: ["Esa", "Financial", "Food Packs"],

abuse: [

"Children",

"Rape",

"Abandonment",
164

"Neglect",

"VAW-C",

"Physical Abuse",

],

},

applications: [],

selectedForm: {},

attributes: [],

dates: [],

selectedScheduleDate: "",

proof: "",

selectedAssistance: "",

cash: "",

remarks: "",

isInterview: false,

filters: {

search: "",

type: "all",

assistance: "all",

},

};

},

created() {

if (Object.keys(this.$route.query).length) {

this.filters.search = this.$route.query.id;

setTimeout(() => {

this.showApplicationModalForm(this.$route.query.id);
165

}, 1000);

this.getAssistanceApplications();

},

methods: {

readURL(event) {

let reader = new FileReader();

reader.readAsDataURL(event.target.files[0]);

reader.onload = (input) => {

const image = new Image();

image.src = input.target.result;

image.onload = () => {

this.proof = document.getElementById("banner").files[0];

document.getElementById("bannerPreview").style.backgroundImage =

"url(" + input.target.result + ")";

};

};

},

async getAssistanceApplications() {

try {

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(


166

`${serverSideUrlApi}/admin-applications/${this.slug}?search=$
{this.filters.search}&type=${this.filters.type}&assistance=$
{this.filters.assistance}`,

headers

);

this.applications = response.data.data;

} catch (error) {

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

} else {

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

}
167

},

async showApplicationModalForm(id) {

try {

this.selectedForm = {};

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(

`${serverSideUrlApi}/admin-applications/${this.slug}/form/${id}`,

headers

);

this.selectedForm = response.data.data;

setTimeout(() => {

this.toggleApplicationModal();

let application = this.applications.find(

(data) =>

data.reference_no === id && data.application_status === null

);

if (application) {

this.applications.find(

(data) => data.reference_no === id

).application_status = "Reviewed";

}, 500);

} catch (error) {
168

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

} else {

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

},

async changeApplicationProcessStatus(actionType) {

try {

let data = {

action_type: actionType,

};
169

if (actionType === "interview") {

data["interview_schedule_date"] = this.selectedScheduleDate

? new Date(this.selectedScheduleDate)

: "";

data["interview_schedule_date_text"] = this.selectedScheduleDate

? new Date(this.selectedScheduleDate).toLocaleString("en-US", {

year: "numeric",

month: "long",

day: "numeric",

hour: "numeric",

minute: "numeric",

hour12: true,

})

: "";

if (actionType === "release") {

data = new FormData();

data.append("action_type", actionType);

data.append("proof", this.proof);

data.append("assistance", this.selectedAssistance);

data.append("cash", this.cash === "" ? 0 : this.cash);

data.append("remarks", this.remarks);

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},
170

};

let response = await axios.patch(

`${serverSideUrlApi}/admin-applications/${this.slug}/form/$
{this.selectedForm.id}/`,

data,

headers

);

this.toast.success("Update Successfully!");

this.selectedForm = response.data.data;

this.getAssistanceApplications();

if (actionType === "interview") {

this.toggleSchedulingModal();

if (actionType === "release") {

this.toggleReleasedModal();

} catch (error) {

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {
171

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

} else {

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

},

checkIfDataIsNone(data) {

if (!data) {

return "N/A";

return data;

},

clearSearch() {

this.filters.search = "";

this.getAssistanceApplications();

},

toggleSchedulingModal(actionType) {

if (actionType === "interview") {

this.isInterview = true;

document.getElementById("exampleModal").style.overflow = "scroll";
172

$("#inputScheduleModal").modal("toggle");

},

toggleApplicationModal() {

$("#exampleModal").modal("toggle");

},

toggleReleasedModal() {

document.getElementById("exampleModal").style.overflow = "scroll";

$("#inputReleasedModal").modal("toggle");

},

gotoToUser(id) {

this.$router.push({ name: "Beneficiaries", query: { id: id } });

},

},

watch: {

selectedAssistance(val) {

this.selectedAssistance = val;

},

},

computed: {

selectedSubClientCategoryList() {

if (this.$route.params.slug === "financial-assistance") {

return this.subClientCategoryOptions["financial"];

if (this.$route.params.slug === "disaster-and-calamity-assistance") {

return this.subClientCategoryOptions["disaster_calamity"];

if (this.$route.params.slug === "abuse") {


173

return this.subClientCategoryOptions["abuse"];

return [];

},

},

};

</script>

<style scoped>

.banner-upload {

position: relative;

margin: 0 0 10px 0;

.banner-upload .banner-edit {

position: absolute;

right: 12px;

z-index: 1;

top: 10px;

.banner-upload .banner-edit input {

display: none !important;

.banner-upload .banner-edit input + label {

display: inline-block;

width: 34px;

height: 34px;
174

margin-bottom: 0;

border-radius: 2px;

background: #ffffff;

border: 1px solid transparent;

box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.12);

cursor: pointer;

font-weight: normal;

transition: all 0.2s ease-in-out;

.banner-upload .banner-edit input + label:hover {

background: #f1f1f1;

border-color: #d6d6d6;

.banner-upload .banner-preview {

width: 100%;

height: 450px;

position: relative;

border-radius: 2px;

border: 3px solid #f8f8f8;

box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);

background: black;

.banner-upload .banner-preview > div {

width: 100%;

height: 100%;

border-radius: 2px;

background-size: contain;
175

background-repeat: no-repeat;

background-position: center;

.download-attachment {

padding: 5px;

border: 1px solid gray;

border-radius: 5px;

color: white;

background: gray;

.application-status {

text-align: center;

font-size: 6vh;

white-space: break-spaces;

font-weight: 700;

</style>

BeneficiaryView

<template>

<div>

<div class="input-group mb-3">

<input

type="text"

class="form-control"

placeholder="Search System ID or Name or Mobile Number"

v-model="filters.search"

@keyup.enter="getBeneficiaries()"
176

/>

<button

class="btn btn-outline-secondary"

type="button"

@click="clearSearch()"

>

Clear

</button>

<button

class="btn btn-outline-secondary"

type="button"

id="button-addon2"

@click="getBeneficiaries()"

>

Search

</button>

</div>

<table class="table table-bordered">

<thead>

<tr>

<th>#</th>

<th scope="col">System ID</th>

<th scope="col">Name</th>

<th scope="col">Mobile number</th>

<th scope="col">Created at</th>

<th scope="col">Recent applied</th>

</tr>
177

</thead>

<tbody v-if="beneficiaries.length">

<tr

v-for="(beneficiary, index) in beneficiaries"

v-bind:key="beneficiary.id"

@click="showProfileModal(beneficiary.system_id)"

>

<td>{{ index + 1 }}</td>

<td>{{ beneficiary.system_id }}</td>

<td>{{ beneficiary.name }}</td>

<td>{{ beneficiary.mobile_number }}</td>

<td>

{{ new Date(beneficiary.created_at).toLocaleString("en-US") }}

</td>

<td>{{ `${beneficiary.recent_applied.client_category} $
{beneficiary.recent_applied.sub_client_category ? '/' : ''} $
{beneficiary.recent_applied.sub_client_category ?
beneficiary.recent_applied.sub_client_category : ''}` }}</td>

</tr>

</tbody>

<tbody v-if="!beneficiaries.length">

<tr>

<td colspan="100%" class="text-center">No beneficiary found!</td>

</tr>

</tbody>

</table>

<!-- Profile Modal -->

<div
178

class="modal fade"

id="exampleModal"

data-bs-backdrop="static"

tabindex="-1"

aria-labelledby="exampleModalLabel"

aria-hidden="true"

>

<div class="modal-dialog modal-xl">

<div class="modal-content" v-if="Object.keys(this.selectedForm).length">

<div class="modal-header">

<h3 class="modal-title fs-5" id="exampleModalLabel"></h3>

<button

type="button"

class="close"

data-dismiss="modal"

>

<span aria-hidden="true">&times;</span

><span class="sr-only">Close</span>

</button>

</div>

<div class="modal-body">

<div class="row g-3">

<div class="col-12">

<div class="text-center mb-5">

<img

:src="selectedForm.avatar"

width="200"
179

alt="avatar"

/>

</div>

</div>

<div class="col-12">

<div class="row g-3">

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>System ID</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="checkIfDataIsNone(selectedForm.system_id)"

readonly

/>

</div>

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Name</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="checkIfDataIsNone(selectedForm.name)"
180

readonly

/>

</div>

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Sex</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="checkIfDataIsNone(selectedForm.sex)"

readonly

/>

</div>

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Age</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="checkIfDataIsNone(selectedForm.age)"

readonly

/>

</div>
181

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Date of Birth</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(

new Date(

selectedForm.date_of_birth

).toLocaleDateString('en-US')

"

readonly

/>

</div>

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Mobile Number</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="
182

checkIfDataIsNone(selectedForm.mobile_number)

"

readonly

/>

</div>

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Civil Status</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="

checkIfDataIsNone(selectedForm.civil_status)

"

readonly

/>

</div>

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Religion</label

>

<input

type="text"

class="form-control"

id="validationDefault01"
183

v-bind:value="checkIfDataIsNone(selectedForm.religion)"

readonly

/>

</div>

<div class="col-4 form-group">

<label for="validationDefault01" class="form-label"

>Nationality</label

>

<input

type="text"

class="form-control"

id="validationDefault01"

v-bind:value="checkIfDataIsNone(selectedForm.nationality)"

readonly

/>

</div>

</div>

</div>

</div>

</div>

<div class="modal-footer">

<button

type="button"

class="btn btn-secondary"

data-dismiss="modal"

>

Close
184

</button>

</div>

</div>

</div>

</div>

<!-- Profile Modal -->

</div>

</template>

<script>

import axios from "axios";

import { useToast } from "vue-toastification";

import intialData from "../intialData";

const serverSideUrlApi = intialData.serverSideUrlApi;

export default {

setup() {

const toast = useToast();

return { toast };

},

data() {

return {

beneficiaries: [],

selectedForm: {},

filters: {
185

search: "",

type: "all",

},

};

},

created() {

if (Object.keys(this.$route.query).length) {

this.filters.search = this.$route.query.id;

setTimeout(() => {

this.showProfileModal(this.$route.query.id);

}, 1000);

this.getBeneficiaries();

},

methods: {

async getBeneficiaries() {

try {

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(

`${serverSideUrlApi}/admin-beneficiaries/?search=${this.filters.search}`,

headers

);

this.beneficiaries = response.data.data;
186

} catch (error) {

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

} else {

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

},

async showProfileModal(slug) {

try {

this.selectedForm = {};

let headers = {
187

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(

`${serverSideUrlApi}/admin-beneficiaries/${slug}`,

headers

);

this.selectedForm = response.data.data;

setTimeout(() => {

this.toggleProfileModal();

}, 100);

} catch (error) {

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {
188

message = "Something went wrong, Please contact the administrator.";

} else {

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

},

checkIfDataIsNone(data) {

if (!data) {

return "N/A";

return data;

},

clearSearch() {

this.filters.search = "";

this.getBeneficiaries();

},

toggleProfileModal() {

$("#exampleModal").modal("toggle");

},

},

};

</script>

<style scoped></style>
189

Chart Report View

<template>

<div>

<div class="d-flex justify-content-end">

<button class="btn btn-primary" @click="printChart">Print</button>

</div>

<Bar id="my-chart-id" :options="chartOptions" :data="chartData" />

</div>

</template>

<script>

import { Bar } from "vue-chartjs";

import {

Chart as ChartJS,

Title,

Tooltip,

Legend,

BarElement,

CategoryScale,

LinearScale,

} from "chart.js";

ChartJS.register(

Title,

Tooltip,

Legend,

BarElement,
190

CategoryScale,

LinearScale

);

import axios from "axios";

import { useToast } from "vue-toastification";

import intialData from "../intialData";

const serverSideUrlApi = intialData.serverSideUrlApi;

export default {

name: "BarChart",

components: { Bar },

setup() {

const toast = useToast();

return { toast };

},

created() {

this.getReport();

},

data() {

return {

chartReport: {},

newData: [0, 0, 0, 0, 0],

};

},
191

methods: {

async getReport() {

try {

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(

`${serverSideUrlApi}/admin-chart-report`,

headers

);

this.chartReport = response.data.assisted_applicants;

this.newData = [

this.chartReport["Financial Assistance"],

this.chartReport["Disaster and Calamity Assistance"],

this.chartReport["Senior Citizen"],

this.chartReport["Children conflict with the law and Child at risk"],

this.chartReport["Abuse"],

];

} catch (error) {

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;
192

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

} else {

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

},

printChart() {

var canvasEle = document.getElementById("my-chart-id");

var win = window.open("", "Print", "height=600,width=1500");

win.document.write(

"<br><div><img style='border: 1px solid gray;' src='" +

canvasEle.toDataURL() +

"' width='1000' /></div>"

);

setTimeout(function () {

win.document.close();

win.focus();
193

win.print();

setTimeout(() => {

win.close();

}, 500);

}, 200);

},

getRandomColor() {

var letters = "0123456789ABCDEF".split("");

var color = "#";

for (var i = 0; i < 6; i++) {

color += letters[Math.floor(Math.random() * 16)];

return color;

},

},

computed: {

chartData() {

return {

labels: [

"Financial Assistance",

"Disaster and Calamity Assistance",

"Senior Citizen",

"Children conflict with the law and Child at risk",

"Abuse",

],

datasets: [

{
194

data: this.newData,

backgroundColor: [

"rgba(255, 99, 132, 0.2)",

"rgba(54, 162, 235, 0.2)",

"rgba(255, 206, 86, 0.2)",

"rgba(75, 192, 192, 0.2)",

"rgba(153, 102, 255, 0.2)",

],

},

],

};

},

chartOptions() {

return {

responsive: true,

plugins: {

title: {

display: true,

text: "Most Applied Application",

position: "top",

},

legend: {

display: false,

},

},

};

},
195

},

};

</script>

<style scoped></style>

Home view

<template>

<main>

<div>

<div class="ibox">

<div class="ibox-title">

<h2>Recent Announcement</h2>

<div class="ibox-tools">

<a class="collapse-link" style="font-size: 24px">

<i class="fa fa-chevron-up"></i>

</a>

</div>

</div>

<div class="ibox-content">

<div class="feed-activity-list">

<div

class="row feed-element"

v-for="announcement in recentAnnouncement.slice(0, 1)"

v-bind:key="announcement.id"

>

<div

class="col-3 ibox-content text-center announcement-banner"


196

:style="`background: url(${announcement.banner})`"

></div>

<div class="col-9">

<h4>{{ announcement.title }}</h4>

<strong>{{ capitalize(announcement.author) }}</strong

>&nbsp;

<small class="text-muted">{{

new Date(announcement.created_at).toLocaleString("en-US")

}}</small>

<div class="description">

{{ hyperlink(announcement.description) }}

<div id="desc"></div>

<div class="fade-away"></div>

</div>

</div>

</div>

</div>

</div>

</div>

</div>

<div>

<h2></h2>

<div>

<div class="ibox">

<div class="ibox-title">

<h2>Not Review Applications</h2>

</div>
197

<div class="ibox-content">

<div class="row">

<div class="col-lg-4">

<div class="ibox">

<div class="ibox-title">

<h5>Financial Assistance</h5>

</div>

<div class="ibox-content">

<h1 class="no-margins">

{{ notReviewApplications["Financial Assistance"] }}

</h1>

</div>

</div>

</div>

<div class="col-lg-4">

<div class="ibox">

<div class="ibox-title">

<h5>Disaster and Calamity Assistance</h5>

</div>

<div class="ibox-content">

<h1 class="no-margins">

{{

notReviewApplications[

"Disaster and Calamity Assistance"

}}

</h1>
198

</div>

</div>

</div>

<div class="col-lg-4">

<div class="ibox">

<div class="ibox-title">

<h5>Senior Citizen</h5>

</div>

<div class="ibox-content">

<h1 class="no-margins">

{{ notReviewApplications["Senior Citizen"] }}

</h1>

</div>

</div>

</div>

<div class="col-lg-4">

<div class="ibox">

<div class="ibox-title">

<h5>Children conflict with the law and Child at risk</h5>

</div>

<div class="ibox-content">

<h1 class="no-margins">

{{

notReviewApplications[

"Children conflict with the law and Child at risk"

}}
199

</h1>

</div>

</div>

</div>

<div class="col-lg-4">

<div class="ibox">

<div class="ibox-title">

<h5>Abuse</h5>

</div>

<div class="ibox-content">

<h1 class="no-margins">

{{ notReviewApplications["Abuse"] }}

</h1>

</div>

</div>

</div>

</div>

</div>

</div>

</div>

</div>

<div>

<div class="ibox">

<div class="ibox-title">

<h2>Today's Appointments</h2>

</div>
200

<div class="ibox-content inspinia-timeline">

<div class="timeline-item" v-if="todaysAppointment.length">

<div

class="row"

v-for="appointment in todaysAppointment"

v-bind:key="appointment.id"

>

<div class="col-1 date">

<i class="fa fa-users"></i>

{{

new Date(appointment.date).toLocaleTimeString("en-US", {

hour: "2-digit",

minute: "2-digit",

hour12: true,

})

}}

</div>

<div class="col-11 content no-top-border">

<h4 class="m-b-xs">

<strong>

{{

appointment.application_status === "Approved"

? "For release assistance"

: "For interview"

}}

</strong>

</h4>
201

<p class="m-b-xs">

<strong>

{{ appointment.assessment.client_category }}

</strong>

</p>

<p v-if="appointment.application_status === 'Approved'">

{{

`Schedule date for releasing assistance with ${appointment.name}`

}}

</p>

<p v-if="appointment.application_status === 'For Interview'">

{{ `Background interview with ${appointment.name}` }}

</p>

</div>

</div>

</div>

<div class="timeline-item" v-if="!todaysAppointment.length">

<div class="row ml-2">

<h3>No appoinment for today</h3>

</div>

</div>

</div>

</div>

</div>

</main>

</template>
202

<script>

import axios from "axios";

import { useToast } from "vue-toastification";

import intialData from "../intialData";

const serverSideUrlApi = intialData.serverSideUrlApi;

export default {

setup() {

const toast = useToast();

return { toast };

},

data() {

return {

recentAnnouncement: [],

notReviewApplications: {},

todaysAppointment: [],

};

},

created() {

this.getDashboardDatas();

},

methods: {

async getDashboardDatas() {

try {

let headers = {
203

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(

`${serverSideUrlApi}/admin-dashboard-data/`,

headers

);

this.recentAnnouncement = response.data.recent_announcements;

this.notReviewApplications = response.data.not_review_applicants;

this.todaysAppointment = response.data.todays_appoinments;

} catch (error) {

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";


204

} else {

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

},

capitalize(text) {

return text ? text.charAt(0).toUpperCase() + text.slice(1) : text;

},

hyperlink(textContent) {

let newTextContent = textContent.replace(

/(https?:\/\/[^\s]+)/g,

(href) => `<a href="${href}" target='_blank'>${href}</a>`

);

let doc = new DOMParser().parseFromString(

`<span>${newTextContent}</span>`,

"text/xml"

);

let newDiv = document.createElement("div");

newDiv.innerHTML = doc.firstChild.innerHTML;

setTimeout(() => {

let divDesc = document.querySelector("#desc");

divDesc.appendChild(newDiv);

}, 100);

},

},
205

};

</script>

<style scoped>

.description {

position: relative;

overflow: hidden;

height: 170px;

white-space: break-spaces;

display: flex;

.fade-away {

height: 100px;

position: absolute;

background: linear-gradient(to bottom, transparent, white);

bottom: 0;

width: 100%;

.announcement-banner {

background-repeat: no-repeat !important;

background-size: contain !important;

background-position: center !important;

background-color: black !important;

</style>

Log in View

<template>
206

<main>

<div class="middle-box loginscreen animated fadeInDown">

<div>

<form @submit.prevent="signIn()">

<div class="mb-3 text-center">

<img src="/static/assets/mswd.png" width="250" />

</div>

<div class="text-center">

<h2 class="h3 mb-3 fw-normal">MSWD Admin App</h2>

</div>

<div class="form-group">

<label for="floatingInput">Email address</label>

<input

type="email"

class="form-control"

id="floatingInput"

v-model="email"

/>

</div>

<div class="form-group">

<label for="floatingPassword">Password</label>

<input

type="password"

class="form-control"

id="floatingPassword"

v-model="password"
207

/>

</div>

<button class="w-100 btn btn-lg btn-primary mt-4" type="submit">

Sign in

</button>

</form>

<div class="text-center">

<p class="m-t"><small>&copy; MSWD App thesis project 2022</small></p>

</div>

</div>

</div>

</main>

</template>

<script>

import axios from "axios";

import { useToast } from "vue-toastification";

import intialData from "../intialData";

const serverSideUrlApi = intialData.serverSideUrlApi;

export default {

setup() {

const toast = useToast();

return { toast };

},
208

data() {

return {

email: "",

password: "",

};

},

methods: {

async signIn() {

if (!this.email || !this.password) {

this.toast.warning("Please fill up the empty fields.");

return;

if (!this.isEmail(this.email)) {

this.toast.error(`${this.email} is not a valid email address.`);

return;

try {

let data = {

email: this.email,

password: this.password,

};

let response = await axios.post(

`${serverSideUrlApi}/admin-login/`,

data

);

this.toast.success(response.data.message);

localStorage.isLogin = true;
209

localStorage.token = response.data.data.token;

setTimeout(() => {

location.reload();

}, 500);

} catch (error) {

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

} else {

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

},
210

isEmail(email) {

return /[\w\d\.-]+@[\w\d\.-]+\.[\w\d\.-]+/.test(email);

},

},

};

</script>

<style scoped></style>

Look up View

<template>

<div>

<div class="input-group mb-3">

<input

type="text"

class="form-control"

placeholder="Ref ID only"

v-model="filters.search"

@keyup.enter="getAssistanceApplications()"

/>

<button

class="btn btn-outline-secondary"

type="button"

@click="clearSearch()"

>

Clear

</button>

<button
211

class="btn btn-outline-secondary"

type="button"

id="button-addon2"

@click="getAssistanceApplications()"

>

Search

</button>

<button

class="btn btn-outline-secondary"

type="button"

@click="printReport()"

>

Print

</button>

</div>

<div class="d-flex mb-4">

<div class="form-group w-25">

<label for="inputSelect">Case</label>

<select

id="inputSelect"

class="form-control"

v-model="filters.case"

@change="getAssistanceApplications()"

>

<option value="all" selected>All</option>

<option value="financial-assistance">Financial Assistance</option>

<option value="disaster-and-calamity-assistance">
212

Disaster and Calamity Assistance

</option>

<option value="senior-citezen">Senior Citizen</option>

<option value="children-conflict-with-the-law-and-child-at-risk">

Children conflict with the law and Child at risk

</option>

<option value="abuse">Abuse</option>

</select>

</div>

<div class="form-group w-25 ml-3">

<label for="inputSelect">Assistance</label>

<select

id="inputSelect"

class="form-control"

v-model="filters.assistance"

@change="getAssistanceApplications()"

>

<option value="all" selected>All</option>

<option

:value="subClient"

v-for="(subClient, index) in selectedSubClientCategoryList"

v-bind:key="index"

>

{{ subClient }}

</option>

</select>

</div>
213

<div class="form-group w-25 ml-3">

<label for="inputSelect">Beneficiary</label>

<select

id="inputSelect"

class="form-control"

v-model="filters.beneficiary"

@change="getAssistanceApplications()"

>

<option value="all" selected>All</option>

<option

:value="beneficiary.system_id"

v-for="(beneficiary, index) in beneficiaries"

v-bind:key="index"

>

{{ beneficiary.name }}

</option>

</select>

</div>

</div>

<table class="table table-bordered">

<thead>

<tr>

<th>#</th>

<th scope="col">Ref ID</th>

<th scope="col" colspan="2">Case</th>

<th scope="col">Beneficiary ID</th>

<th scope="col">Beneficiary</th>
214

<th scope="col">Assisted Type</th>

<th scope="col">Asisted when</th>

<th scope="col">Cash release</th>

</tr>

</thead>

<tbody v-if="applications.length">

<tr

v-for="(application, index) in applications"

v-bind:key="application.id"

@click.prevent="showApplicationModalForm(application.reference_no)"

>

<td>{{ index + 1 }}</td>

<td>

{{ application.reference_no }}

<button

class="btn btn-sm btn-primary"

@click.stop="gotoToApplication(application)"

>

Redirect

</button>

</td>

<td>

{{ application.assessment.client_category }}

</td>

<td>

{{ application.assessment.sub_client_category }}

</td>
215

<td>

{{ application.user }}

<button

class="btn btn-sm btn-primary"

@click.stop="gotoToUser(application.user)"

>

Redirect

</button>

</td>

<td>{{ application.name }}</td>

<td>

{{ application.assistance }}

</td>

<td>

{{ new Date(application.updated_at).toLocaleString("en-US") }}

</td>

<td>

{{ priceFormat(application.cash) }}

</td>

</tr>

<tr>

<td colspan="8"><strong>TOTAL</strong></td>

<td>

<strong>{{ priceFormat(applicationsAmount) }}</strong>

</td>

</tr>

</tbody>
216

<tbody v-if="!applications.length">

<tr>

<td colspan="100%" class="text-center">No application found!</td>

</tr>

<tr>

<td colspan="8"><strong>TOTAL</strong></td>

<td>

<strong>{{ priceFormat(0) }}</strong>

</td>

</tr>

</tbody>

</table>

<!-- MODAL -->

<div

class="modal fade"

id="exampleModal"

data-bs-backdrop="static"

tabindex="-1"

aria-labelledby="exampleModalLabel"

aria-hidden="true"

>

<div class="modal-dialog modal-xl">

<div class="modal-content" v-if="Object.keys(this.selectedForm).length">

<div class="modal-header">

<h3 class="modal-title fs-5" id="exampleModalLabel"></h3>

<button type="button" class="close" data-dismiss="modal">

<span aria-hidden="true">&times;</span
217

><span class="sr-only">Close</span>

</button>

</div>

<div class="modal-body">

<div class="row g-3">

<div class="col-6">

<div class="form-group">

<div class="i-checks">

<label>

<input

type="radio"

v-model="selectedForm.assistance"

value="cash"

name="assist_release"

readonly

/>

Cash

</label>

</div>

<div class="i-checks">

<label>

<input

type="radio"

v-model="selectedForm.assistance"

value="others"

name="assist_release"

readonly
218

/>

Others

</label>

</div>

</div>

<div class="form-group">

<label for="floatingTextarea2">Cash</label>

<input

class="form-control"

id="floatingTextarea2"

v-model="selectedForm.cash"

placeholder="0"

readonly

/>

</div>

<div class="form-group">

<label for="floatingTextarea2">Remarks</label>

<textarea

class="form-control"

id="floatingTextarea2"

style="height: 100px"

v-model="selectedForm.remarks"

readonly

></textarea>

</div>

</div>

<div class="col-6">
219

<div class="mb-5">

<div><label>Proof of received assistance</label></div>

<div>

<img

style="max-width: 500px"

:src="selectedForm.proof"

alt="avatar"

/>

</div>

</div>

</div>

</div>

</div>

<div class="modal-footer">

<button

type="button"

class="btn btn-secondary"

data-dismiss="modal"

>

Close

</button>

</div>

</div>

</div>

</div>

<!-- MODAL -->

<!-- HIDDEN PRINT -->


220

<div id="report" v-show="false">

<table style="width: 100%;">

<thead>

<tr>

<th>#</th>

<th scope="col">Ref ID</th>

<th scope="col" colspan="2">Case</th>

<th scope="col">Beneficiary</th>

<th scope="col">Assisted Type</th>

<th scope="col">Asisted when</th>

<th scope="col">Cash release</th>

</tr>

</thead>

<tbody v-if="applications.length">

<tr

v-for="(application, index) in applications"

v-bind:key="application.id"

@click.prevent="showApplicationModalForm(application.reference_no)"

>

<td>{{ index + 1 }}</td>

<td>

{{ application.reference_no }}

</td>

<td>

{{ application.assessment.client_category }}

</td>

<td>
221

{{ application.assessment.sub_client_category }}

</td>

<td>{{ application.name }}</td>

<td>

{{ application.assistance }}

</td>

<td>

{{ new Date(application.updated_at).toLocaleString("en-US") }}

</td>

<td>

{{ priceFormat(application.cash) }}

</td>

</tr>

<tr>

<td colspan="7"><strong>TOTAL</strong></td>

<td>

<strong>{{ priceFormat(applicationsAmount) }}</strong>

</td>

</tr>

</tbody>

<tbody v-if="!applications.length">

<tr>

<td colspan="100%" class="text-center">No application found!</td>

</tr>

<tr>

<td colspan="7"><strong>TOTAL</strong></td>

<td>
222

<strong>{{ priceFormat(0) }}</strong>

</td>

</tr>

</tbody>

</table>

</div>

<!-- HIDDEN PRINT -->

</div>

</template>

<script>

import axios from "axios";

import { useToast } from "vue-toastification";

import intialData from "../intialData";

const serverSideUrl = intialData.serverSideUrl;

const serverSideUrlApi = intialData.serverSideUrlApi;

export default {

setup() {

const toast = useToast();

return { toast };

},

data() {

return {

Url: serverSideUrl,
223

applications: [],

selectedForm: {},

attributes: [],

dates: [],

subClientCategoryOptions: {

financial: [

"Educational Assistance",

"Death Assistance",

"Medical Assistance",

],

disaster_calamity: ["Esa", "Financial", "Food Packs"],

abuse: [

"Children",

"Rape",

"Abandonment",

"Neglect",

"VAW-C",

"Physical Abuse",

],

},

isInterview: false,

filters: {

search: "",

case: "all",

assistance: "all",

beneficiary: "all",

},
224

beneficiaries: [],

applicationsAmount: 0,

};

},

created() {

this.getAssistanceApplications();

this.getBeneficiaries();

},

methods: {

async getBeneficiaries() {

try {

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(

`${serverSideUrlApi}/admin-beneficiaries/`,

headers

);

this.beneficiaries = response.data.data;

} catch (error) {

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {


225

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

} else {

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

},

async getAssistanceApplications() {

try {

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(

`${serverSideUrlApi}/admin-applications/?search=$
{this.filters.search}&case=${this.filters.case}&assistance=$
{this.filters.assistance}&beneficiary=${this.filters.beneficiary}`,
226

headers

);

this.applications = response.data.data;

let applicationsAmount = 0;

this.applications.map((element) => {

applicationsAmount += element.cash;

});

this.applicationsAmount = applicationsAmount;

} catch (error) {

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

} else {

message = "Something went wrong, Please contact the administrator.";


227

this.toast.error(message);

},

async showApplicationModalForm(id) {

try {

this.selectedForm = {};

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(

`${serverSideUrlApi}/admin-applications/form/${id}`,

headers

);

this.selectedForm = response.data.data;

setTimeout(() => {

this.toggleProofModal();

}, 500);

} catch (error) {

let message = "";

if (Object.keys(error).length) {

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;
228

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

} else {

message = "Something went wrong, Please contact the administrator.";

this.toast.error(message);

},

checkIfDataIsNone(data) {

if (!data) {

return "N/A";

return data;

},

clearSearch() {

this.filters.search = "";

this.getAssistanceApplications();

},

toggleSchedulingModal(actionType) {
229

if (actionType === "interview") {

this.isInterview = true;

$("#inputScheduleModal").modal("toggle");

},

toggleApplicationModal() {

$("#exampleModal").modal("toggle");

},

gotoToUser(id) {

this.$router.push({ name: "Beneficiaries", query: { id: id } });

},

gotoToApplication(application) {

let path = application.assessment.client_category.replaceAll(" ", "-");

this.$router.push({

path: `/assistances/${path}`,

query: { id: application.reference_no },

});

},

priceFormat(value) {

const val = (value / 1).toFixed(2).replace(",", ".");

return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");

},

toggleProofModal() {

$("#exampleModal").modal("toggle");

},

printReport() {

let mywindow = window.open("", "PRINT", "fullscreen=yes,width=550");


230

mywindow.document.write('<html><head><style>table, th, td {border:1px solid


black; text-align: center;}</style></head>');

mywindow.document.write('<body>');

mywindow.document.write(document.getElementById("report").innerHTML);

mywindow.document.write("</body></html>");

mywindow.document.close();

setTimeout(() => {

mywindow.focus();

mywindow.print();

}, 500);

setTimeout(() => {

mywindow.close();

}, 500);

return;

},

computed: {

selectedSubClientCategoryList() {

if (this.filters.case === "financial-assistance") {

return this.subClientCategoryOptions["financial"];

if (this.filters.case === "disaster-and-calamity-assistance") {

return this.subClientCategoryOptions["disaster_calamity"];

if (this.filters.case === "abuse") {

return this.subClientCategoryOptions["abuse"];

}
231

return [];

},

},

};

</script>

<style scoped></style>

Mobile

Account Page

<template>

<ion-page>

<ion-header>

<ion-toolbar>

<ion-title>Settings</ion-title>

</ion-toolbar>

</ion-header>

<ion-content>

<div>

<ion-item lines="full" detail="true" button @click="gotoProfile()">

<ion-icon :icon="person" slot="start"></ion-icon>

<ion-label>Profile</ion-label>

</ion-item>

<ion-item lines="full" button @click="signOut()">

<ion-icon :icon="logOutOutline" slot="start"></ion-icon>

<ion-label>Sign Out</ion-label>

</ion-item>
232

</div>

</ion-content>

</ion-page>

</template>

<script>

import { defineComponent } from "vue";

import {

IonPage,

IonContent,

IonItem,

IonIcon,

IonLabel,

IonToolbar,

IonHeader,

IonTitle,

toastController,

alertController,

} from "@ionic/vue";

import { person, logOutOutline } from "ionicons/icons";

import axios from "axios";

import { serverSideUrlApi } from "../intialData";

export default defineComponent({

name: "AccountPage",
233

setup() {

return {

person,

logOutOutline,

};

},

components: {

IonPage,

IonContent,

IonItem,

IonIcon,

IonLabel,

IonToolbar,

IonHeader,

IonTitle,

},

methods: {

async openToastMessage(message) {

const toast = await toastController.create({

message: message,

duration: 2000,

position: "bottom",

});

return toast.present();

},

async openAlertMessage(type, message) {

const alert = await alertController.create({


234

cssClass: "my-custom-class",

header: type,

message: message,

buttons: ["OK"],

});

await alert.present();

},

async signOut() {

try {

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(`${serverSideUrlApi}/logout/`, headers);

this.openToastMessage(response.data.message);

localStorage.isLogin = "";

localStorage.token = "";

localStorage.hasProfile = "";

localStorage.hasProcessingApplication = "";

localStorage.removeItem("otp_status");

localStorage.removeItem("otp_timer");

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} catch (error) {

let message = "";


235

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

localStorage.hasProfile = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

this.openAlertMessage("Error!", message);

},

gotoProfile() {

this.$router.push({ name: "ViewProfilePage" });

},

},

});

</script>

<style scoped>

ion-item {
236

--ion-background-color: #ffffff !important;

ion-icon {

color: black;

</style>

Announcement Page

<template>

<ion-page>

<ion-header>

<ion-toolbar>

<ion-buttons slot="start">

<ion-back-button color="primary"></ion-back-button>

</ion-buttons>

</ion-toolbar>

</ion-header>

<ion-content>

<div>

<ion-card

v-for="announcement in announcements"

v-bind:key="announcement.id"

>

<div class="ion-text-center" style="background-color: black;">

<img

alt="..."

:src="`${locationURL}${announcement.banner}`"

v-if="announcement.banner"
237

height="250"

/>

</div>

<ion-card-header>

<ion-card-title>{{ announcement.title }}</ion-card-title>

<ion-card-subtitle

><strong>{{ capitalize(announcement.author) }}</strong>

{{

new Date(announcement.created_at).toLocaleString("en-US")

}}</ion-card-subtitle

>

</ion-card-header>

<ion-card-content>

<div>

<div class="description">

<p>{{ announcement.description }}</p>

<div class="fade-away"></div>

</div>

<div class="ion-text-end">

<ion-button

fill="clear"

@click="viewAnnouncement(announcement.id)"

>Read More</ion-button

>

</div>

</div>

</ion-card-content>
238

</ion-card>

</div>

</ion-content>

</ion-page>

</template>

<script>

import { defineComponent } from "vue";

import {

IonPage,

IonContent,

IonButton,

IonHeader,

IonToolbar,

IonButtons,

IonBackButton,

IonCard,

IonCardContent,

IonCardHeader,

IonCardSubtitle,

IonCardTitle,

toastController,

alertController,

} from "@ionic/vue";

import axios from "axios";


239

import { serverSideUrl, serverSideUrlApi } from "../intialData";

export default defineComponent({

name: "AnnouncementsPage",

components: {

IonPage,

IonContent,

IonButton,

IonHeader,

IonToolbar,

IonButtons,

IonBackButton,

IonCard,

IonCardContent,

IonCardHeader,

IonCardSubtitle,

IonCardTitle,

},

ionViewWillEnter() {

this.getAnnouncements();

},

data() {

return {

locationURL: serverSideUrl,

announcements: [],

};

},
240

methods: {

async openToastMessage(message) {

const toast = await toastController.create({

message: message,

duration: 2000,

position: "bottom",

});

return toast.present();

},

async openAlertMessage(type, message) {

const alert = await alertController.create({

cssClass: "my-custom-class",

header: type,

message: message,

buttons: ["OK"],

});

await alert.present();

},

async getAnnouncements() {

try {

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(

`${serverSideUrlApi}/announcements/`,
241

headers

);

this.announcements = response.data.data;

} catch (error) {

let message = "";

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

message = "Session already expired, Please login again.";

localStorage.isLogin = "";

localStorage.token = "";

localStorage.hasProfile = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

this.openAlertMessage("Error!", message);

},

viewAnnouncement(id) {

this.$router.push({

name: "ViewAnnouncement",
242

params: {

id: id,

},

});

},

capitalize(text) {

return text ? text.charAt(0).toUpperCase() + text.slice(1) : text;

},

},

});

</script>

<style scoped>

.description {

position: relative;

overflow: hidden;

height: 65px;

white-space: break-spaces;

.fade-away {

height: 100px;

position: absolute;

background: linear-gradient(to bottom, transparent, white);

bottom: 0;

width: 100%;

img {
243

vertical-align: middle;

</style>

Form page

<template>

<ion-page>

<ion-header>

<ion-toolbar v-if="slideSelected === 1">

<ion-buttons slot="start">

<ion-button @click="closeModal()">

<ion-icon slot="icon-only" :icon="close" color="primary"></ion-icon>

</ion-button>

</ion-buttons>

<ion-buttons slot="end">

<ion-button fill="clear" color="primary" @click="goNext(2)">

Next

</ion-button>

</ion-buttons>

</ion-toolbar>

<ion-toolbar v-if="slideSelected === 2">

<ion-buttons slot="start">

<ion-button fill="clear" color="primary" @click="goBack(1)">

Back

</ion-button>

</ion-buttons>

<ion-buttons slot="end">

<ion-button fill="clear" color="primary" @click="goNext(3)">


244

Next

</ion-button>

</ion-buttons>

</ion-toolbar>

<ion-toolbar v-if="slideSelected === 3">

<ion-buttons slot="start">

<ion-button fill="clear" color="primary" @click="goBack(2)">

Back

</ion-button>

</ion-buttons>

</ion-toolbar>

</ion-header>

<ion-content ref="content">

<div>

<swiper

@swiper="onSwiper"

:slides-per-view="1"

:allowTouchMove="false"

:noSwiping="true"

>

<swiper-slide>

<div class="__container-form">

<div class="ion-text-center ion-margin-bottom title">

<h1>Clients Identifying Information</h1>

</div>

<div class="form">

<ion-item lines="none">
245

<ion-label position="floating"

><span>Lastname </span

><small

class="small-warn-label"

:style="

errors && !clientIdentifyingInformation.lastname

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small

></ion-label

>

<ion-input

v-model="clientIdentifyingInformation.lastname"

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Firstname </span

><small

class="small-warn-label"

:style="

errors && !clientIdentifyingInformation.firstname

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small
246

></ion-label

>

<ion-input

v-model="clientIdentifyingInformation.firstname"

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Middlename </span

><small

class="small-warn-label"

:style="

errors && !clientIdentifyingInformation.middlename

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small

></ion-label

>

<ion-input

v-model="clientIdentifyingInformation.middlename"

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Ext.(Jr, Sr) </span

><small class="small-warn-label"
247

>(Optional)</small

></ion-label

>

<ion-input

v-model="clientIdentifyingInformation.extension"

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Sex </span

><small

class="small-warn-label"

:style="

errors && !clientIdentifyingInformation.sex

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small

></ion-label

>

<ion-select v-model="clientIdentifyingInformation.sex">

<ion-select-option value="Male">Male</ion-select-option>

<ion-select-option value="Female">Female</ion-select-option>

</ion-select>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"
248

><span>Date of Birth </span

><small

class="small-warn-label"

:style="

errors && !clientIdentifyingInformation.date_of_birth

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small

></ion-label

>

<ion-input

type="date"

placeholder=""

v-model="clientIdentifyingInformation.date_of_birth"

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Region </span

><small

class="small-warn-label"

:style="

errors && !clientIdentifyingInformation.region

? 'color: red !important;'

: 'color: gray;'

"
249

>(Required)</small

></ion-label

>

<!-- <ion-select v-model="clientIdentifyingInformation.region">

<ion-select-option value="10">X</ion-select-option>

</ion-select> -->

<ion-input

v-model="clientIdentifyingInformation.region"

readonly

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Province </span

><small

class="small-warn-label"

:style="

errors && !clientIdentifyingInformation.province

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small

></ion-label

>

<!-- <ion-select v-model="clientIdentifyingInformation.province">

<ion-select-option value="Misamis Oriental"

>Misamis Oriental</ion-select-option
250

>

</ion-select> -->

<ion-input

v-model="clientIdentifyingInformation.province"

readonly

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>City/Municipality </span

><small

class="small-warn-label"

:style="

errors &&

!clientIdentifyingInformation.city_or_municipality

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small

></ion-label

>

<!-- <ion-select

v-model="clientIdentifyingInformation.city_or_municipality"

>

<ion-select-option value="10"

>Cagayan De Oro City</ion-select-option

>
251

</ion-select> -->

<ion-input

v-model="clientIdentifyingInformation.city_or_municipality"

readonly

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>District </span

><small class="small-warn-label"

>(Required)</small

></ion-label

>

<!-- <ion-select v-model="clientIdentifyingInformation.district">

<ion-select-option value="2nd congressional district"

>2nd congressional district</ion-select-option

>

</ion-select> -->

<ion-input

v-model="clientIdentifyingInformation.district"

readonly

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Barangay </span

><small
252

class="small-warn-label"

:style="

errors && !clientIdentifyingInformation.barangay

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small

></ion-label

>

<ion-select v-model="clientIdentifyingInformation.barangay">

<ion-select-option value="Aplaya">Aplaya</ion-select-option>

<ion-select-option value="Bobuntugan"

>Bobuntugan</ion-select-option

>

<ion-select-option value="Danao">Danao</ion-select-option>

<ion-select-option

value="Ignacio S. Cruz

"

>Ignacio S. Cruz

</ion-select-option>

<ion-select-option value="Jampason"

>Jampason</ion-select-option

>

<ion-select-option value="Kimaya">Kimaya</ion-select-option>

<ion-select-option value="Corrales"

>Corrales</ion-select-option

>
253

<ion-select-option

value="Lower Jasaan (Ubos)

"

>Lower Jasaan (Ubos)

</ion-select-option>

<ion-select-option value="Luz Banzon (Kiog-ang)"

>Luz Banzon (Kiog-ang)</ion-select-option

>

<ion-select-option value="Natubo">Natubo</ion-select-option>

<ion-select-option

value="San Antonio

"

>San Antonio

</ion-select-option>

<ion-select-option value="San Isidro"

>San Isidro</ion-select-option

>

<ion-select-option value="San Nicolas (Kilumba)"

>San Nicolas (Kilumba)</ion-select-option

>

<ion-select-option value="Solana">Solana</ion-select-option>

<ion-select-option value="Upper Jasaan (Ibabaw)"

>Upper Jasaan (Ibabaw)</ion-select-option

>

</ion-select>

</ion-item>

<ion-item lines="none">
254

<ion-label position="floating"

><span>No./Street/Purok </span

><small class="small-warn-label"

>(Optional)</small

></ion-label

>

<ion-input

v-model="clientIdentifyingInformation.no_street_or_purok"

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Place of Birth </span

><small

class="small-warn-label"

:style="

errors && !clientIdentifyingInformation.place_of_birth

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small

></ion-label

>

<ion-input

v-model="clientIdentifyingInformation.place_of_birth"

></ion-input>

</ion-item>
255

<ion-item lines="none">

<ion-label position="floating"

><span>Relationship to Beneficiary </span

><small

class="small-warn-label"

:style="

errors &&

!clientIdentifyingInformation.relationship_to_beneficiary

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small

></ion-label

>

<ion-select

v-model="

clientIdentifyingInformation.relationship_to_beneficiary

"

>

<ion-select-option value="Self">Self</ion-select-option>

<ion-select-option value="Father">Father</ion-select-option>

<ion-select-option value="Mother">Mother</ion-select-option>

<ion-select-option value="Brother"

>Brother</ion-select-option

>

<ion-select-option value="Sister">Sister</ion-select-option>

<ion-select-option value="Son">Son</ion-select-option>
256

<ion-select-option value="Daughter"

>Daughter</ion-select-option

>

</ion-select>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Civil Status </span

><small

class="small-warn-label"

:style="

errors && !clientIdentifyingInformation.civil_status

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small

></ion-label

>

<ion-select

v-model="clientIdentifyingInformation.civil_status"

>

<ion-select-option value="Single">Single</ion-select-option>

<ion-select-option value="Married"

>Married</ion-select-option

>

<ion-select-option value="Others">Others</ion-select-option>

</ion-select>
257

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Religion </span

><small class="small-warn-label"

>(Optional)</small

></ion-label

>

<ion-input

v-model="clientIdentifyingInformation.religion"

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Nationality </span

><small class="small-warn-label"

>(Optional)</small

></ion-label

>

<ion-input

v-model="clientIdentifyingInformation.nationality"

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Highest Educational Attainment </span

><small class="small-warn-label"
258

>(Optional)</small

></ion-label

>

<ion-select

v-model="

clientIdentifyingInformation.highest_educational_attainment

"

>

<ion-select-option

value="less than secondary high school graduation"

>Less than secondary high school

graduation</ion-select-option

>

<ion-select-option

value="secondary high school diploma or equivalent"

>Secondary high school diploma or

equivalent</ion-select-option

>

<ion-select-option value="some postsecondary education"

>Some postsecondary education</ion-select-option

>

<ion-select-option

value="postsecondary certificate, diploma or degree"

>Postsecondary certificate, diploma or

degree</ion-select-option

>

</ion-select>
259

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Skills/Occupation </span

><small

class="small-warn-label"

:style="

errors &&

!clientIdentifyingInformation.skills_or_occupation

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small

></ion-label

>

<ion-input

v-model="clientIdentifyingInformation.skills_or_occupation"

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Estimated Monthly Income </span

><small

class="small-warn-label"

:style="

errors &&

!clientIdentifyingInformation.estimated_monthly_income
260

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small

></ion-label

>

<ion-input

v-model="

clientIdentifyingInformation.estimated_monthly_income

"

></ion-input>

</ion-item>

</div>

</div>

</swiper-slide>

<swiper-slide>

<div class="__container-form">

<div class="ion-text-center ion-margin-bottom title">

<h1>Beneficiary's Family Composition</h1>

</div>

<div>

<div class="ion-text-center">

<ion-button @click="openFamilyCompositionModal()"

>Add family composition</ion-button

>

</div>

<ion-card
261

v-for="(member, index) in beneficiarysFamilyComposition"

v-bind:key="index"

>

<ion-card-header>

<ion-card-title

>{{ member.lastname }}, {{ member.firstname }}

{{ member.middlename }}</ion-card-title

>

</ion-card-header>

<ion-card-content>

<p>{{ member.sex }}</p>

<p>

{{

new Date(member.date_of_birth).toLocaleDateString(

"en-US",

{ year: "numeric", month: "long", day: "numeric" }

}}

</p>

<p>{{ member.civil_status }}</p>

<p>{{ member.relationship }}</p>

<p>{{ member.highest_educational_attainment }}</p>

<p>{{ member.skills_or_occupation }}</p>

<p>{{ member.estimated_monthly_income }}</p>

</ion-card-content>

</ion-card>

</div>
262

</div>

</swiper-slide>

<swiper-slide>

<div class="__container-form">

<div class="ion-text-center ion-margin-bottom title">

<h1>Assessment</h1>

</div>

<div class="form">

<ion-item lines="none">

<ion-label position="floating"

><span>Problem/s Presented </span

><small

class="small-warn-label"

:style="

errors && !assessment.problems_presented

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small

></ion-label

>

<ion-input

v-model="assessment.problems_presented"

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"
263

><span>Social Worker's Assessment </span

><small class="small-warn-label"

>(Optional)</small

></ion-label

>

<ion-input

v-model="assessment.social_workers_assessment"

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Client Category </span

><small

class="small-warn-label"

:style="

errors && !assessment.client_category

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small

></ion-label

>

<ion-select v-model="assessment.client_category">

<ion-select-option value="Financial Assistance"

>Financial Assistance</ion-select-option

>

<ion-select-option value="Disaster and Calamity Assistance"


264

>Disaster and Calamity Assistance</ion-select-option

>

<ion-select-option value="Senior Citizen"

>Senior Citizen</ion-select-option

>

<ion-select-option

value="Children conflict with the law and Child at risk"

>Children conflict with the law and Child at

risk</ion-select-option

>

<ion-select-option value="Abuse">Abuse</ion-select-option>

</ion-select>

</ion-item>

<ion-item

lines="none"

v-if="selectedSubClientCategoryList.length"

>

<ion-label position="floating"

><span>Client Sub-Category </span

><small

class="small-warn-label"

:style="

errors && !assessment.sub_client_category

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small
265

></ion-label

>

<ion-select v-model="assessment.sub_client_category">

<ion-select-option

v-for="(

subClient, index

) in selectedSubClientCategoryList"

v-bind:key="index"

:value="subClient"

>{{ subClient }}</ion-select-option

>

</ion-select>

</ion-item>

</div>

<div class="ion-text-center ion-margin-bottom title">

<h1>Attachments</h1>

</div>

<div class="form">

<ion-item lines="none">

<ion-label position="floating"

><span>Barangay Certificate of Indigency</span

><small

class="small-warn-label"

:style="

errors && !attachments.problems_presented

? 'color: red !important;'

: 'color: gray;'
266

"

>(Required)</small

></ion-label

>

<ion-input

type="file"

placeholder=""

@change="readURL"

></ion-input>

</ion-item>

<ion-item lines="none">

<ion-label position="floating"

><span>Valid ID</span

><small

class="small-warn-label"

:style="

errors && !attachments.problems_presented

? 'color: red !important;'

: 'color: gray;'

"

>(Required)</small

></ion-label

>

<ion-input

type="file"

placeholder=""

@change="readURL2"
267

></ion-input>

</ion-item>

</div>

<div class="ion-margin-top ion-text-center form">

<ion-button

mode="ios"

expand="block"

@click="submitApplicantForm()"

>Apply now</ion-button

>

</div>

</div>

</swiper-slide>

</swiper>

</div>

</ion-content>

</ion-page>

</template>

<script>

import { defineComponent, ref } from "vue";

import {

IonPage,

IonHeader,

IonToolbar,

IonButtons,

IonButton,
268

IonIcon,

IonContent,

IonItem,

IonLabel,

IonInput,

IonSelect,

IonSelectOption,

IonCard,

IonCardHeader,

IonCardTitle,

IonCardContent,

modalController,

toastController,

alertController,

} from "@ionic/vue";

import { close } from "ionicons/icons";

import FamilyCompositionModal from "../components/FamilyCompositionModal";

import { Swiper, SwiperSlide } from "swiper/vue";

import axios from "axios";

import { serverSideUrlApi } from "../intialData";

export default defineComponent({

name: "FormModal",

components: {
269

IonPage,

IonHeader,

IonToolbar,

IonButtons,

IonButton,

IonIcon,

IonContent,

IonItem,

IonLabel,

IonInput,

IonSelect,

IonSelectOption,

IonCard,

IonCardHeader,

IonCardTitle,

IonCardContent,

Swiper,

SwiperSlide,

},

setup() {

const content = ref();

return {

close,

content,

};

},

mounted() {
270

if (localStorage.hasProfile) {

let profileDetails = JSON.parse(localStorage.hasProfile);

setTimeout(() => {

this.clientIdentifyingInformation.lastname = profileDetails.lastname;

this.clientIdentifyingInformation.firstname = profileDetails.firstname;

this.clientIdentifyingInformation.middlename =

profileDetails.middlename;

this.clientIdentifyingInformation.extension = profileDetails.extension;

this.clientIdentifyingInformation.sex = profileDetails.sex;

this.clientIdentifyingInformation.date_of_birth = new Date(

profileDetails.date_of_birth

).toLocaleDateString("en-CA");

this.clientIdentifyingInformation.civil_status =

profileDetails.civil_status;

this.clientIdentifyingInformation.religion = profileDetails.religion;

this.clientIdentifyingInformation.nationality =

profileDetails.nationality;

}, 100);

},

data() {

return {

subClientCategoryOptions: {

financial: [

"Educational Assistance",

"Death Assistance",

"Medical Assistance",
271

],

disaster_calamity: ["Esa", "Financial", "Food Packs"],

abuse: [

"Children",

"Rape",

"Abandonment",

"Neglect",

"VAW-C",

"Physical Abuse",

],

},

clientIdentifyingInformation: {

lastname: "",

firstname: "",

middlename: "",

extension: "",

sex: "",

date_of_birth: "",

region: "Region X",

province: "Misamis Oriental",

city_or_municipality: "Jasaan",

district: "2nd district",

barangay: "",

no_street_or_purok: "",

place_of_birth: "",

relationship_to_beneficiary: "",

civil_status: "",
272

religion: "",

nationality: "",

highest_educational_attainment: "",

skills_or_occupation: "",

estimated_monthly_income: "",

},

beneficiarysFamilyComposition: [],

assessment: {

problems_presented: "",

social_workers_assessment: "",

client_category: "",

sub_client_category: "",

},

attachments: {

certificate_of_indigency: "",

valid_id: "",

},

slideSelected: 1,

swiper: null,

errors: 0,

};

},

methods: {

readURL(input) {

if (input.target.files && input.target.files[0]) {

this.attachments.certificate_of_indigency = input.target.files[0];

}
273

},

readURL2(input) {

if (input.target.files && input.target.files[0]) {

this.attachments.valid_id = input.target.files[0];

},

async openToastMessage(message) {

const toast = await toastController.create({

message: message,

duration: 2000,

position: "bottom",

});

return toast.present();

},

async openAlertMessage(type, message) {

const alert = await alertController.create({

cssClass: "my-custom-class",

header: type,

message: message,

buttons: ["OK"],

});

await alert.present();

},

async openFamilyCompositionModal() {

const modal = await modalController.create({

component: FamilyCompositionModal,

cssClass: "my-custom-class",
274

});

await modal.present();

const { data } = await modal.onWillDismiss();

if (data != undefined) {

this.beneficiarysFamilyComposition.push(data.result);

},

async submitApplicantForm() {

try {

console.log(this.attachments);

if (this.FormAssessmentValidation()) return;

let data = new FormData();

data.append(

"client_identifying_information",

JSON.stringify(this.clientIdentifyingInformation)

);

data.append(

"beneficiarys_family_composition",

JSON.stringify(this.beneficiarysFamilyComposition)

);

data.append("assessment", JSON.stringify(this.assessment));

data.append(

"certificate_of_indigency",

this.attachments.certificate_of_indigency

);

data.append("valid_id", this.attachments.valid_id);
275

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.post(

`${serverSideUrlApi}/apply-assistance/`,

data,

headers

);

this.openToastMessage(response.data.message);

localStorage.hasProcessingApplication = 1;

this.$router.replace({ name: "History" });

} catch (error) {

let message = "";

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

localStorage.hasProfile = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);
276

} else {

message = "Something went wrong, Please contact the administrator.";

this.openAlertMessage("Error!", message);

},

FormClientIdentifyingInformationValidation() {

let {

lastname,

firstname,

middlename,

sex,

date_of_birth,

region,

province,

city_or_municipality,

barangay,

place_of_birth,

relationship_to_beneficiary,

civil_status,

skills_or_occupation,

estimated_monthly_income,

} = this.clientIdentifyingInformation;

let errors = 0;

if (!lastname) errors = 1;
277

if (!firstname) errors = 1;

if (!middlename) errors = 1;

if (!sex) errors = 1;

if (!date_of_birth) errors = 1;

if (!region) errors = 1;

if (!province) errors = 1;

if (!city_or_municipality) errors = 1;

if (!barangay) errors = 1;

if (!place_of_birth) errors = 1;

if (!relationship_to_beneficiary) errors = 1;

if (!civil_status) errors = 1;

if (!skills_or_occupation) errors = 1;

if (!estimated_monthly_income) errors = 1;

if (errors) {

this.openToastMessage("Please fill required fields!");

this.errors = errors;

return this.errors;

},

FormAssessmentValidation() {

let { problems_presented, client_category } = this.assessment;

let errors = 0;

if (!problems_presented) errors = 1;

if (!client_category) errors = 1;

if (!this.attachments.certificate_of_indigency) errors = 1;
278

if (!this.attachments.valid_id) errors = 1;

if (errors) {

this.openToastMessage("Please fill required fields!");

this.errors = errors;

return this.errors;

},

onSwiper(swiper) {

this.swiper = swiper;

},

goNext(index) {

if (index === 2) {

if (this.FormClientIdentifyingInformationValidation()) return;

if (index === 3) {

if (this.beneficiarysFamilyComposition.length < 2) {

this.openToastMessage("Please fill maximum 2 family members!");

return;

this.slideSelected = index;

this.swiper.slideTo(index - 1, 500, false);

this.content.$el.scrollToTop(1000);

},

goBack(index) {

this.slideSelected = index;
279

this.swiper.slideTo(index - 1, 500, false);

this.content.$el.scrollToTop(1000);

},

closeModal() {

this.$router.back();

},

},

computed: {

selectedSubClientCategoryList() {

if (this.assessment.client_category === "Financial Assistance") {

return this.subClientCategoryOptions["financial"];

if (

this.assessment.client_category === "Disaster and Calamity Assistance"

) {

return this.subClientCategoryOptions["disaster_calamity"];

if (this.assessment.client_category === "Abuse") {

return this.subClientCategoryOptions["abuse"];

return [];

},

},

});

</script>

<style scoped>
280

div.__container-form {

margin: 2rem auto 2rem auto;

width: 100% !important;

.form {

margin: 0 2.6rem;

.small-warn-label {

color: gray;

ion-item {

border: 1px solid #c8c7cc;

border-radius: 10px;

margin: 10px 0;

--ion-background-color: #ffffff !important;

.title h1 {

font-weight: 600 !important;

</style>

History Page

<template>

<ion-page>

<ion-header>

<ion-toolbar>

<ion-searchbar
281

v-model="search"

placeholder="Search reference no."

show-clear-button="always"

></ion-searchbar>

</ion-toolbar>

</ion-header>

<ion-content>

<div v-if="applicationsHistory.length" class="ion-text-center">

<ion-card

class="ion-text-start"

button="true"

v-for="application in filteredApplicationsHistory"

v-bind:key="application.id"

@click.prevent="showApplicationFormDetails(application.id)"

>

<ion-card-header>

<ion-card-title>

Ref No: {{ application.reference_no }}

</ion-card-title>

<ion-card-subtitle

>Case:

{{ application.assessment.client_category }}</ion-card-subtitle

>

<ion-card-subtitle v-if="application.assessment.sub_client_category"

>Assistance:

{{ application.assessment.sub_client_category }}</ion-card-subtitle

>
282

</ion-card-header>

<ion-card-content>

<span v-if="application.application_status">

{{ application.application_status.toUpperCase() }}

</span>

<span v-if="!application.application_status">{{

"Not yet Review".toUpperCase()

}}</span>

</ion-card-content>

<div class="ion-text-end">

<ion-button

v-if="

!application.application_status ||

application.application_status === 'Reviewed'

"

fill="clear"

color="danger"

@click.stop="showCancelConfirmation(application.id)"

>Cancel</ion-button

>

</div>

</ion-card>

<h5 v-if="!filteredApplicationsHistory.length">

Can't find what your looking for...

</h5>

</div>

<div
283

v-if="!applicationsHistory.length"

class="ion-margin ion-text-center"

>

<h5>You don't have any applied application yet.</h5>

</div>

<ion-fab

slot="fixed"

vertical="bottom"

horizontal="end"

v-if="!pendingApplication.length"

>

<ion-fab-button @click.prevent="applyAssistance()">

<ion-icon :icon="createSharp"></ion-icon>

</ion-fab-button>

</ion-fab>

</ion-content>

</ion-page>

</template>

<script>

import { defineComponent } from "vue";

import {

IonPage,

IonContent,

IonCard,

IonCardContent,

IonCardHeader,
284

IonCardTitle,

IonCardSubtitle,

IonButton,

IonIcon,

IonSearchbar,

IonFab,

IonFabButton,

IonToolbar,

IonHeader,

toastController,

alertController,

} from "@ionic/vue";

import { createSharp } from "ionicons/icons";

import axios from "axios";

import { serverSideUrlApi } from "../intialData";

export default defineComponent({

name: "HistoryPage",

components: {

IonPage,

IonContent,

IonCard,

IonCardContent,

IonCardHeader,

IonCardTitle,
285

IonCardSubtitle,

IonButton,

IonIcon,

IonSearchbar,

IonFab,

IonFabButton,

IonToolbar,

IonHeader,

},

setup() {

return {

createSharp,

};

},

ionViewWillEnter() {

this.getApplicationForms();

},

data() {

return {

search: "",

applicationsHistory: [],

filteredApplicationsHistory: [],

pendingApplication: [],

};

},

methods: {

async openToastMessage(message) {
286

const toast = await toastController.create({

message: message,

duration: 2000,

position: "bottom",

});

return toast.present();

},

async openAlertMessage(type, message) {

const alert = await alertController.create({

cssClass: "my-custom-class",

header: type,

message: message,

buttons: ["OK"],

});

await alert.present();

},

async openConfirmMessage(type, message, data, yesHandler) {

const alert = await alertController.create({

cssClass: "my-custom-class",

header: type,

message: message,

buttons: [

text: "No",

role: "cancel",

cssClass: "secondary",

},
287

text: "Yes",

handler: () => {

yesHandler(data);

},

},

],

});

await alert.present();

},

async applyAssistance() {

this.$router.push({ name: "Form" });

},

async getApplicationForms() {

try {

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(

`${serverSideUrlApi}/applications/`,

headers

);

this.applicationsHistory = response.data.data;

this.filteredApplicationsHistory = this.applicationsHistory;

this.pendingApplication = this.applicationsHistory.filter(
288

(element) =>

element.application_status === "" ||

element.application_status.includes("Reviewed") ||

element.application_status.includes("For Interview") ||

element.application_status.includes("Interviewed") ||

element.application_status.includes("Approved")

);

} catch (error) {

let message = "";

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

message = "Session already expired, Please login again.";

localStorage.isLogin = "";

localStorage.token = "";

localStorage.hasProfile = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

this.openAlertMessage("Error!", message);

}
289

},

showCancelConfirmation(id) {

let data = {

id: id,

};

this.openConfirmMessage(

"Warning!",

"Are you sure you want to proceed?",

data,

this.cancelApplicationForm

);

},

async cancelApplicationForm(params) {

try {

let id = params.id;

let data = {};

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.patch(

`${serverSideUrlApi}/applications/${id}/`,

data,

headers

);

this.openToastMessage(response.data.message);
290

this.getApplicationForms();

} catch (error) {

let message = "";

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

localStorage.hasProfile = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

this.openAlertMessage("Error!", message);

},

showApplicationFormDetails(id) {

this.$router.push({

name: "ViewForm",

params: {

id: id,

},
291

});

},

},

watch: {

search(val) {

if (val) {

this.filteredApplicationsHistory = this.applicationsHistory.filter(

(element) => element.reference_no.includes(val)

);

} else {

this.filteredApplicationsHistory = this.applicationsHistory;

},

},

});

</script>

<style scoped></style>

Home page

<template>

<ion-page>

<!-- <ion-header>

<ion-toolbar>

</ion-toolbar>

</ion-header> -->

<ion-content>

<div class="application-status">
292

<ion-card>

<ion-card-content>

<div class="application" v-if="!hasProcessingApplication">

<h2>You can now apply for any assistance.</h2>

<ion-button

class="ion-text-wrap ion-margin-top"

expand="block"

@click.prevent="applyAssistance()"

>Apply Now!</ion-button

>

</div>

<div class="application" v-if="hasProcessingApplication">

<h2>Your application is currently on-process.</h2>

<ion-button

class="ion-text-wrap ion-margin-top"

expand="block"

@click.prevent="showApplicationFormDetails()"

>Click here to view your application!</ion-button

>

</div>

</ion-card-content>

</ion-card>

</div>

<div>

<ion-accordion-group :value="['first']">

<ion-accordion value="first">

<ion-item slot="header" color="light">


293

<div class="card-header">

<h4>Recent Announcements</h4>

</div>

</ion-item>

<div class="ion-padding" slot="content">

<div>

<ion-card

v-for="announcement in announcements.slice(0, 1)"

v-bind:key="announcement.id"

>

<div class="ion-text-center" style="background-color: black">

<img

alt="..."

:src="`${locationURL}${announcement.banner}`"

v-if="announcement.banner"

height="250"

/>

</div>

<ion-card-header>

<ion-card-title>{{ announcement.title }}</ion-card-title>

<ion-card-subtitle

><strong>{{ capitalize(announcement.author) }}</strong>

{{

new Date(announcement.created_at).toLocaleString(

"en-US"

}}</ion-card-subtitle
294

>

</ion-card-header>

<ion-card-content>

<div>

<div class="description">

<p>{{ announcement.description }}</p>

<div class="fade-away"></div>

</div>

<div class="ion-text-end">

<ion-button

class="read-more-btn"

fill="clear"

@click="viewAnnouncement(announcement.id)"

>Read More</ion-button

>

</div>

</div>

</ion-card-content>

</ion-card>

</div>

<div class="ion-text-center">

<ion-button class="see-more-btn" @click="seeMoreAnnouncements()"

>See more</ion-button

>

</div>

</div>

</ion-accordion>
295

</ion-accordion-group>

</div>

</ion-content>

</ion-page>

</template>

<script>

import { defineComponent } from "vue";

import {

IonPage,

IonContent,

IonButton,

IonAccordion,

IonAccordionGroup,

IonCard,

IonCardContent,

IonCardHeader,

IonCardSubtitle,

IonCardTitle,

toastController,

alertController,

} from "@ionic/vue";

import axios from "axios";

import { serverSideUrl, serverSideUrlApi } from "../intialData";


296

export default defineComponent({

name: "HomePage",

components: {

IonPage,

IonContent,

IonButton,

IonAccordion,

IonAccordionGroup,

IonCard,

IonCardContent,

IonCardHeader,

IonCardSubtitle,

IonCardTitle,

},

ionViewWillEnter() {

this.checkApplications();

this.getAnnouncements();

},

data() {

return {

locationURL: serverSideUrl,

hasProcessingApplication: "",

applicationId: "",

announcements: [],

};

},

methods: {
297

async openToastMessage(message) {

const toast = await toastController.create({

message: message,

duration: 2000,

position: "bottom",

});

return toast.present();

},

async openAlertMessage(type, message) {

const alert = await alertController.create({

cssClass: "my-custom-class",

header: type,

message: message,

buttons: ["OK"],

});

await alert.present();

},

async applyAssistance() {

this.$router.push({ name: "Form" });

},

async checkApplications() {

try {

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};
298

let response = await axios.get(

`${serverSideUrlApi}/check-applications/`,

headers

);

this.hasProcessingApplication = response.data.has_progress_application;

this.applicationId = response.data.application_id;

} catch (error) {

let message = "";

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

message = "Session already expired, Please login again.";

localStorage.isLogin = "";

localStorage.token = "";

localStorage.hasProfile = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

this.openAlertMessage("Error!", message);

},
299

async getAnnouncements() {

try {

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(

`${serverSideUrlApi}/announcements/`,

headers

);

this.announcements = response.data.data;

} catch (error) {

let message = "";

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

message = "Session already expired, Please login again.";

localStorage.isLogin = "";

localStorage.token = "";

localStorage.hasProfile = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

}
300

} else {

message = "Something went wrong, Please contact the administrator.";

this.openAlertMessage("Error!", message);

},

showApplicationFormDetails() {

this.$router.push({

name: "ViewForm",

params: {

id: this.applicationId,

},

});

},

viewAnnouncement(id) {

this.$router.push({

name: "ViewAnnouncement",

params: {

id: id,

},

});

},

seeMoreAnnouncements() {

this.$router.push({

name: "Announcements",

});

},
301

capitalize(text) {

return text ? text.charAt(0).toUpperCase() + text.slice(1) : text;

},

},

});

</script>

<style scoped>

.application {

text-align: center;

color: black;

.card-header {

display: flex;

display: flex;

justify-content: space-between;

align-items: end;

margin: 0 10px;

ion-button.see-more-btn::part(native) {

width: 150px;

ion-button.read-more-btn::part(native) {

padding: unset !important;

.description {

position: relative;
302

overflow: hidden;

height: 65px;

.fade-away {

height: 100px;

position: absolute;

background: linear-gradient(to bottom, transparent, white);

bottom: 0;

width: 100%;

.application-status {

position: absolute;

bottom: 0;

width: 100%;

</style>

Login Page

<template>

<ion-page>

<ion-content>

<div class="login-content">

<div class="logo">

<img src="../assets/mswd.png" />

</div>

<div class="ion-text-center message-header">

<h2>Welcome to MSWD Assistance App</h2>

</div>
303

<div>

<ion-item lines="none">

<ion-label position="floating">Mobile number</ion-label>

<ion-input

type="text"

inputmode="numeric"

@keyup="checkMobileNumber($event)"

@ionBlur="maskedMobileNumber()"

v-model="mobileNumber"

></ion-input>

</ion-item>

</div>

<div>

<ion-item lines="none">

<ion-label position="floating">Password</ion-label>

<ion-input

:type="EyePass"

clearOnEdit="false"

v-model="password"

></ion-input>

<ion-button class="eyebtn" @click.self="showHidePass()">

<ion-icon

slot="icon-only"

:icon="EyeIcon"

color="primary"

></ion-icon>

</ion-button>
304

</ion-item>

</div>

<div class="ion-margin-top ion-padding-top">

<ion-button mode="ios" expand="block" @click="formValidation()"

>Sign In</ion-button

>

</div>

<div class="ion-margin-top ion-margin-bottom">

<ion-button mode="ios" expand="block" @click="gotoSignUp()"

>Sign Up</ion-button

>

</div>

</div>

</ion-content>

</ion-page>

</template>

<script>

import { defineComponent } from "vue";

import {

IonPage,

IonContent,

IonItem,

IonLabel,

IonInput,

IonButton,

IonIcon,
305

modalController,

toastController,

alertController,

} from "@ionic/vue";

import { eye, eyeOff } from "ionicons/icons";

import TwoStepAuthModal from "../components/TwoStepAuthModal";

import axios from "axios";

import { serverSideUrlApi } from "../intialData";

export default defineComponent({

name: "LoginPage",

components: {

IonPage,

IonContent,

IonItem,

IonLabel,

IonInput,

IonButton,

IonIcon,

},

setup() {

return {

eye,

eyeOff,
306

};

},

data() {

return {

mobileNumber: "",

password: "",

EyeIcon: this.eyeOff,

EyeStatus: false,

EyePass: "password",

};

},

methods: {

async openToastMessage(message) {

const toast = await toastController.create({

message: message,

duration: 2000,

position: "bottom",

});

return toast.present();

},

async openAlertMessage(type, message) {

const alert = await alertController.create({

cssClass: "my-custom-class",

header: type,

message: message,

buttons: ["OK"],

});
307

await alert.present();

},

async openTwoStepAuthModal() {

const modal = await modalController.create({

component: TwoStepAuthModal,

cssClass: "my-custom-class",

componentProps: {

type: "login",

mobileNumber: this.mobileNumber,

},

});

await modal.present();

const { data } = await modal.onWillDismiss();

if (data != undefined) {

setTimeout(() => {

this.$router.replace({ name: "Home" });

}, 500);

},

showHidePass() {

if (this.EyeStatus == false) {

this.EyeStatus = true;

this.EyeIcon = this.eye;

this.EyePass = "text";

} else {

this.EyeStatus = false;

this.EyeIcon = this.eyeOff;
308

this.EyePass = "password";

},

formValidation() {

if (!this.mobileNumber || !this.password) {

this.openToastMessage("Please fill up the empty fields.");

return;

if (this.mobileNumber.length !== 13) {

this.openToastMessage("Incorrect mobile format.");

return;

this.signIn();

},

checkMobileNumber(event) {

let inputtedKey = event.key;

let inputtedValue = event.target.value;

let allowChar = ["+", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];

if (inputtedValue) {

if (allowChar.includes(inputtedKey)) {

this.mobileNumber = inputtedValue;

} else {

this.mobileNumber = inputtedValue.replace(inputtedKey, "");

},

maskedMobileNumber() {
309

if (this.mobileNumber) {

if (this.mobileNumber[0] === "0") {

this.mobileNumber = this.mobileNumber.replace("0", "+63");

if (this.mobileNumber.length !== 13) {

this.openToastMessage("Incorrect mobile format.");

} else if (this.mobileNumber[0] === "9") {

this.mobileNumber = `+63${this.mobileNumber}`;

if (this.mobileNumber.length !== 13) {

this.openToastMessage("Incorrect mobile format.");

} else {

if (this.mobileNumber[0] !== "+") {

this.mobileNumber = `+${this.mobileNumber}`;

if (this.mobileNumber.length !== 13) {

this.openToastMessage("Incorrect mobile format.");

},

gotoSignUp() {

this.$router.push({ name: "Register" });

},

async signIn() {

try {

let data = {
310

mobile_number: this.mobileNumber,

password: this.password,

};

let response = await axios.post(`${serverSideUrlApi}/login/`, data);

this.openToastMessage(response.data.message);

localStorage.removeItem("otp_status");

localStorage.removeItem("otp_timer");

localStorage.isLogin = true;

localStorage.token = response.data.data.token;

localStorage.hasProfile = Object.keys(response.data.data.profile).length

? JSON.stringify(response.data.data.profile)

: "";

localStorage.hasProcessingApplication = response.data.data

.has_processing_application

? true

: "";

this.openTwoStepAuthModal();

} catch (error) {

let message = "";

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

localStorage.hasProfile = "";
311

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

this.openAlertMessage("Error!", message);

},

},

});

</script>

<style scoped>

.logo {

display: flex;

justify-content: center;

.logo img {

height: 200px;

.login-content {

width: 80%;

position: absolute;

top: 50%;

left: 50%;
312

transform: translate(-50%, -50%);

.message-header {

margin-bottom: 30px;

.eyebtn {

position: absolute;

right: 20px;

top: 11px;

padding: 0 !important;

--background: transparent;

z-index: 2;

--padding-start: 0;

--padding-end: 0;

--padding-top: 0;

--padding-bottom: 0;

--box-shadow: 0;

ion-item {

border: 1px solid #c8c7cc;

border-radius: 10px;

margin: 10px 0;

--ion-background-color: #ffffff !important;

</style>

Profile Page

<template>
313

<ion-page>

<ion-content>

<div class="login-content">

<div class="logo">

<img src="../assets/mswd.png" />

</div>

<div class="ion-text-center message-header">

<h2>Welcome to MSWD Assistance App</h2>

</div>

<div>

<ion-item lines="none">

<ion-label position="floating">Mobile number</ion-label>

<ion-input

type="text"

inputmode="numeric"

@keyup="checkMobileNumber($event)"

@ionBlur="maskedMobileNumber()"

v-model="mobileNumber"

></ion-input>

</ion-item>

</div>

<div>

<ion-item lines="none">

<ion-label position="floating">Password</ion-label>

<ion-input

:type="EyePass"

clearOnEdit="false"
314

v-model="password"

></ion-input>

<ion-button class="eyebtn" @click.self="showHidePass()">

<ion-icon

slot="icon-only"

:icon="EyeIcon"

color="primary"

></ion-icon>

</ion-button>

</ion-item>

</div>

<div class="ion-margin-top ion-padding-top">

<ion-button mode="ios" expand="block" @click="formValidation()"

>Sign In</ion-button

>

</div>

<div class="ion-margin-top ion-margin-bottom">

<ion-button mode="ios" expand="block" @click="gotoSignUp()"

>Sign Up</ion-button

>

</div>

</div>

</ion-content>

</ion-page>

</template>

<script>
315

import { defineComponent } from "vue";

import {

IonPage,

IonContent,

IonItem,

IonLabel,

IonInput,

IonButton,

IonIcon,

modalController,

toastController,

alertController,

} from "@ionic/vue";

import { eye, eyeOff } from "ionicons/icons";

import TwoStepAuthModal from "../components/TwoStepAuthModal";

import axios from "axios";

import { serverSideUrlApi } from "../intialData";

export default defineComponent({

name: "LoginPage",

components: {

IonPage,

IonContent,

IonItem,
316

IonLabel,

IonInput,

IonButton,

IonIcon,

},

setup() {

return {

eye,

eyeOff,

};

},

data() {

return {

mobileNumber: "",

password: "",

EyeIcon: this.eyeOff,

EyeStatus: false,

EyePass: "password",

};

},

methods: {

async openToastMessage(message) {

const toast = await toastController.create({

message: message,

duration: 2000,

position: "bottom",

});
317

return toast.present();

},

async openAlertMessage(type, message) {

const alert = await alertController.create({

cssClass: "my-custom-class",

header: type,

message: message,

buttons: ["OK"],

});

await alert.present();

},

async openTwoStepAuthModal() {

const modal = await modalController.create({

component: TwoStepAuthModal,

cssClass: "my-custom-class",

componentProps: {

type: "login",

mobileNumber: this.mobileNumber,

},

});

await modal.present();

const { data } = await modal.onWillDismiss();

if (data != undefined) {

setTimeout(() => {

this.$router.replace({ name: "Home" });

}, 500);

}
318

},

showHidePass() {

if (this.EyeStatus == false) {

this.EyeStatus = true;

this.EyeIcon = this.eye;

this.EyePass = "text";

} else {

this.EyeStatus = false;

this.EyeIcon = this.eyeOff;

this.EyePass = "password";

},

formValidation() {

if (!this.mobileNumber || !this.password) {

this.openToastMessage("Please fill up the empty fields.");

return;

if (this.mobileNumber.length !== 13) {

this.openToastMessage("Incorrect mobile format.");

return;

this.signIn();

},

checkMobileNumber(event) {

let inputtedKey = event.key;

let inputtedValue = event.target.value;

let allowChar = ["+", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
319

if (inputtedValue) {

if (allowChar.includes(inputtedKey)) {

this.mobileNumber = inputtedValue;

} else {

this.mobileNumber = inputtedValue.replace(inputtedKey, "");

},

maskedMobileNumber() {

if (this.mobileNumber) {

if (this.mobileNumber[0] === "0") {

this.mobileNumber = this.mobileNumber.replace("0", "+63");

if (this.mobileNumber.length !== 13) {

this.openToastMessage("Incorrect mobile format.");

} else if (this.mobileNumber[0] === "9") {

this.mobileNumber = `+63${this.mobileNumber}`;

if (this.mobileNumber.length !== 13) {

this.openToastMessage("Incorrect mobile format.");

} else {

if (this.mobileNumber[0] !== "+") {

this.mobileNumber = `+${this.mobileNumber}`;

if (this.mobileNumber.length !== 13) {

this.openToastMessage("Incorrect mobile format.");

}
320

},

gotoSignUp() {

this.$router.push({ name: "Register" });

},

async signIn() {

try {

let data = {

mobile_number: this.mobileNumber,

password: this.password,

};

let response = await axios.post(`${serverSideUrlApi}/login/`, data);

this.openToastMessage(response.data.message);

localStorage.removeItem("otp_status");

localStorage.removeItem("otp_timer");

localStorage.isLogin = true;

localStorage.token = response.data.data.token;

localStorage.hasProfile = Object.keys(response.data.data.profile).length

? JSON.stringify(response.data.data.profile)

: "";

localStorage.hasProcessingApplication = response.data.data

.has_processing_application

? true

: "";

this.openTwoStepAuthModal();

} catch (error) {
321

let message = "";

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

localStorage.hasProfile = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

this.openAlertMessage("Error!", message);

},

},

});

</script>

<style scoped>

.logo {

display: flex;

justify-content: center;
322

.logo img {

height: 200px;

.login-content {

width: 80%;

position: absolute;

top: 50%;

left: 50%;

transform: translate(-50%, -50%);

.message-header {

margin-bottom: 30px;

.eyebtn {

position: absolute;

right: 20px;

top: 11px;

padding: 0 !important;

--background: transparent;

z-index: 2;

--padding-start: 0;

--padding-end: 0;

--padding-top: 0;

--padding-bottom: 0;

--box-shadow: 0;

}
323

ion-item {

border: 1px solid #c8c7cc;

border-radius: 10px;

margin: 10px 0;

--ion-background-color: #ffffff !important;

</style>

Register Page

<template>

<ion-page>

<ion-content>

<div class="container" v-if="!isVerified">

<div class="ion-text-center">

<h1>Before we continue, Let's verify who you are...</h1>

</div>

<div class="ion-margin-top">

<ion-item lines="none">

<ion-label position="floating">Mobile number</ion-label>

<ion-input type="text" inputmode="numeric"


@keyup="checkMobileNumber($event)" @ionBlur="maskedMobileNumber()" v-
model="mobileNumber"></ion-input>

</ion-item>

</div>

<div class="ion-margin-top ion-padding-top">

<ion-button mode="ios" expand="block"


@click="checkInputted()">Send Verification</ion-button>

</div>

<div class="ion-margin-top ion-margin-bottom">


324

<ion-button mode="ios" expand="block" @click="goBack()">Go


Back</ion-button>

</div>

</div>

<div class="container" v-if="isVerified">

<div class="ion-text-center">

<h1>Congrat's you completed the verification, Now let's input your


...</h1>

</div>

<div class="ion-margin-top">

<ion-item lines="none">

<ion-label position="floating">New password</ion-label>

<ion-input :type="EyePass" clearOnEdit="false" v-


model="newPassword"></ion-input>

<ion-button class="eyebtn" @click.self="showHidePass()">

<ion-icon slot="icon-only" :icon="EyeIcon"


color="primary"></ion-icon>

</ion-button>

</ion-item>

<ion-item lines="none">

<ion-label position="floating">Confirm password</ion-label>

<ion-input :type="EyePass" clearOnEdit="false" v-


model="confirmPassword"></ion-input>

<ion-button class="eyebtn" @click.self="showHidePass()">

<ion-icon slot="icon-only" :icon="EyeIcon"


color="primary"></ion-icon>

</ion-button>

</ion-item>

</div>
325

<div class="ion-margin-top ion-padding-top">

<ion-button mode="ios" expand="block"


@click="registerAccount()">Register Account</ion-button>

</div>

</div>

</ion-content>

</ion-page>

</template>

<script>

import { defineComponent } from 'vue';

import { IonPage, IonContent, IonItem, IonLabel, IonInput, IonButton, modalController,


toastController, alertController } from '@ionic/vue';

import { eye, eyeOff } from "ionicons/icons";

import TwoStepAuthModal from '../components/TwoStepAuthModal';

import axios from 'axios';

import { serverSideUrlApi } from '../intialData';

export default defineComponent({

name: 'RegisterPage',

components: { IonPage, IonContent, IonItem, IonLabel, IonInput, IonButton },

setup() {

return {

eye,

eyeOff
326

},

data() {

return {

isVerified: false,

mobileNumber: "",

newPassword: "",

confirmPassword: "",

EyeIcon: this.eyeOff,

EyeStatus: false,

EyePass: "password",

},

methods: {

async openToastMessage(message) {

const toast = await toastController.create({

message: message,

duration: 2000,

position: "bottom"

});

return toast.present();

},

async openAlertMessage(type, message) {

const alert = await alertController.create({

cssClass: "my-custom-class",

header: type,

message: message,
327

buttons: ["OK"],

});

await alert.present();

},

async openTwoStepAuthModal() {

const modal = await modalController.create({

component: TwoStepAuthModal,

cssClass: "my-custom-class",

componentProps: {

type: "register",

mobileNumber: this.mobileNumber

});

await modal.present();

const { data } = await modal.onWillDismiss();

if (data != undefined) {

this.isVerified = data.verify;

},

showHidePass() {

if (this.EyeStatus == false) {

this.EyeStatus = true;

this.EyeIcon = this.eye;

this.EyePass = "text";

} else {

this.EyeStatus = false;

this.EyeIcon = this.eyeOff;
328

this.EyePass = "password";

},

checkMobileNumber(event) {

let inputtedKey = event.key;

let inputtedValue = event.target.value;

let allowChar = ["+", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];

if (inputtedValue) {

if (allowChar.includes(inputtedKey)) {

this.mobileNumber = inputtedValue;

} else {

this.mobileNumber = inputtedValue.replace(inputtedKey, "");

},

maskedMobileNumber() {

if (this.mobileNumber) {

if (this.mobileNumber[0] === "0") {

this.mobileNumber = this.mobileNumber.replace("0", "+63");

if (this.mobileNumber.length !== 13) {

this.openToastMessage("Incorrect mobile format.");

} else if (this.mobileNumber[0] === "9") {

this.mobileNumber = `+63${this.mobileNumber}`;

if (this.mobileNumber.length !== 13) {

this.openToastMessage("Incorrect mobile format.");

}
329

} else {

if (this.mobileNumber[0] !== "+") {

this.mobileNumber = `+${this.mobileNumber}`;

if (this.mobileNumber.length !== 13) {

this.openToastMessage("Incorrect mobile format.");

},

checkInputted() {

if (!this.mobileNumber) {

this.openToastMessage("Please fill up the empty field.");

return;

if (this.mobileNumber.length !== 13) {

this.openToastMessage("Incorrect mobile format.");

return;

this.openTwoStepAuthModal();

},

goBack() {

this.$router.back();

},

async registerAccount() {

if ((!this.newPassword) || (!this.confirmPassword)) {

this.openToastMessage("Please fill up the empty fields.");


330

return;

if (this.newPassword !== this.confirmPassword) {

this.openToastMessage("Confirm password doesn't match the new


password.");

return;

try {

let data = {

"mobile_number": this.mobileNumber,

"password": this.newPassword,

let response = await axios.post(`${serverSideUrlApi}/register/`,


data);

this.openToastMessage(response.data.message);

localStorage.isLogin = true;

localStorage.token = response.data.data.token;

localStorage.hasProfile =
Object.keys(response.data.data.profile).length ?
JSON.stringify(response.data.data.profile) : "";

setTimeout(() => {

this.$router.replace({ name: "Home" });

}, 500);

} catch (error) {

let message = "";

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {


331

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

localStorage.isLogin = "";

localStorage.token = "";

localStorage.hasProfile = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the


administrator.";

this.openAlertMessage("Error!", message);

},

});

</script>

<style scoped>

.eyebtn {

position: absolute;

right: 20px;

top: 11px;

padding: 0 !important;

--background: transparent;
332

z-index: 2;

--padding-start: 0;

--padding-end: 0;

--padding-top: 0;

--padding-bottom: 0;

--box-shadow: 0;

ion-item {

border: 1px solid #c8c7cc;

border-radius: 10px;

margin: 10px 0;

--ion-background-color: #ffffff !important;

</style>

Tabs Page

<template>

<ion-page>

<ion-tabs>

<ion-router-outlet></ion-router-outlet>

<ion-tab-bar slot="bottom">

<ion-tab-button tab="home" href="/tabs/home">

<ion-icon :icon="home" />

<ion-label>Home</ion-label>

</ion-tab-button>

<ion-tab-button tab="history" href="/tabs/history">

<ion-icon :icon="newspaper" />

<ion-label>History</ion-label>
333

</ion-tab-button>

<ion-tab-button tab="account" href="/tabs/account">

<ion-icon :icon="personCircle" />

<ion-label>Account</ion-label>

</ion-tab-button>

</ion-tab-bar>

</ion-tabs>

</ion-page>

</template>

<script>

import { defineComponent } from 'vue';

import { IonTabBar, IonTabButton, IonTabs, IonLabel, IonIcon, IonPage, IonRouterOutlet


} from '@ionic/vue';

import { home, newspaper, personCircle } from 'ionicons/icons';

export default defineComponent({

name: 'TabsPage',

components: { IonLabel, IonTabs, IonTabBar, IonTabButton, IonIcon, IonPage,


IonRouterOutlet },

setup() {

return {

home,

newspaper,

personCircle,

});
334

</script>

View Announcements Page

<template>

<ion-page>

<ion-header>

<ion-toolbar>

<ion-buttons slot="start">

<ion-back-button color="primary"></ion-back-button>

</ion-buttons>

</ion-toolbar>

</ion-header>

<ion-content>

<div v-if="Object.keys(announcement).length">

<div

v-if="announcement.banner"

class="ion-text-center"

style="background-color: black"

>

<img

alt="..."

:src="`${locationURL}${announcement.banner}`"

v-if="announcement.banner"

/>

</div>

<div class="form">

<h2>

{{ announcement.title }}
335

</h2>

</div>

<div class="form">

<strong>{{ capitalize(announcement.author) }}</strong

><br />

<small>{{

new Date(announcement.created_at).toLocaleString("en-US")

}}</small>

</div>

<div class="form description">

{{ hyperlink(announcement.description, announcement.id) }}

<div :id="`desc${announcement.id}`"></div>

</div>

</div>

</ion-content>

</ion-page>

</template>

<script>

import { defineComponent } from "vue";

import {

IonPage,

IonContent,

IonHeader,

IonToolbar,

IonButtons,

IonBackButton,
336

toastController,

alertController,

} from "@ionic/vue";

import axios from "axios";

import { serverSideUrl, serverSideUrlApi } from "../intialData";

export default defineComponent({

name: "ViewAnnouncementPage",

components: {

IonPage,

IonContent,

IonHeader,

IonToolbar,

IonButtons,

IonBackButton,

},

data() {

return {

locationURL: serverSideUrl,

id: this.$route.params.id,

announcement: {},

};

},

created() {

this.getAnnouncement();
337

},

methods: {

async openToastMessage(message) {

const toast = await toastController.create({

message: message,

duration: 2000,

position: "bottom",

});

return toast.present();

},

async openAlertMessage(type, message) {

const alert = await alertController.create({

cssClass: "my-custom-class",

header: type,

message: message,

buttons: ["OK"],

});

await alert.present();

},

async getAnnouncement() {

try {

let headers = {

headers: {

Authorization: `Token ${localStorage.token}`,

},

};

let response = await axios.get(


338

`${serverSideUrlApi}/announcement/${this.id}`,

headers

);

this.announcement = response.data.data;

} catch (error) {

let message = "";

if (Object.hasOwn(error.response.data, "message")) {

message = error.response.data.message;

} else if (Object.hasOwn(error.response.data, "detail")) {

message = error.response.data.detail;

if (message.includes("Invalid token.")) {

message = "Session already expired, Please login again.";

localStorage.isLogin = "";

localStorage.token = "";

localStorage.hasProfile = "";

setTimeout(() => {

this.$router.replace({ name: "Login" });

}, 500);

} else {

message = "Something went wrong, Please contact the administrator.";

this.openAlertMessage("Error!", message);

},

capitalize(text) {

return text ? text.charAt(0).toUpperCase() + text.slice(1) : text;


339

},

hyperlink(textContent, id) {

if (!textContent) return;

let newTextContent = textContent.replace(

/(https?:\/\/[^\s]+)/g,

(href) =>

`<a href="${href}" target="_blank" style="position: relative;z-index:


999;">${href}</a>`

);

let doc = new DOMParser().parseFromString(

`<span>${newTextContent}</span>`,

"text/xml"

);

let newDiv = document.createElement("div");

newDiv.innerHTML = doc.firstChild.innerHTML;

setTimeout(() => {

let divDesc = document.querySelector(`#desc${id}`);

if (!divDesc.hasChildNodes()) {

divDesc.appendChild(newDiv);

} else {

while (divDesc.firstChild) {

divDesc.removeChild(divDesc.firstChild);

divDesc.appendChild(newDiv);

}, 100);

},
340

},

});

</script>

<style scoped>

.form {

margin: 0 2.6rem;

.form h2 {

font-weight: 700;

.description {

margin-top: 10px;

white-space: break-spaces;

img {

vertical-align: middle;

</style>
341
A. Curriculum Vitae

SHANNEN KHATE S. DAILO


Upper, Jasaan Misamis Oriental
Philippines,
9003
Mobile number: 09754810379
Email address: [email protected]

PERSONAL DATA
Age : 22 years old
Gender : Female
Civil status : Single
Date of Birth : December 30, 2000
Place of Birth : Jasaan, Jasaan Misamis Oriental
Religion :Roman Catholic
Citizenship : Filipino
Height : 5’0
Weight : 42 kls.

EDUCATION
TERTIARY: University of Science and Technology of
Southern Philippines
Lower Jasaan, Jasaan Misamis Oriental
Bachelor of Science and Information
Technology

SENIOR HIGH SCHOOL: University of Science and Technology of


2018-2019 Southern Philippines

Lower Jasaan, Jasaan Misamis Oriental


JUNIOR HIGH SCHOOL: Jasaan National High School
2016-2017 Upper Jasaan, Jasaan Misamis Oriental

PRIMARY SCHOOL: Jasaan Central School


2012-2013 Upper, Jasaan Misamis Oriental

SPECIAL SKILLS: Computer Literate, Microsoft Office Suite


Independent and self-sufficient in handling task
Video Editing and Visual graphics creativity.

You might also like