Welcome to my portfolio!

Creating products to improve processes.

About Me

My expertise predominantly lies in the realm of PowerApps and Power Automate, bolstered by formal training and advanced certifications in these platforms.


Over the last two and a half years, I have dedicated myself to crafting bespoke applications for various key stakeholders across Cyprus, reaching an extensive user base of over 2000 individuals during this timeframe.


This hands-on experience has allowed me to refine my proficiency within this domain significantly.


Recognizing the versatility of these skills, I am actively broadening my horizons by delving into Python and HTML (I designed and developed this website) outside of my professional commitments.


I firmly believe that the competencies honed through my work with PowerApps and Power Automate seamlessly translate into other similar technologies, propelling me towards continuous growth and exploration in the dynamic world of app development.

Portfolio

BFC Station Visits Application

This is one of my most recent Projects therefore I would say this is my best work to date.

Project Two Image

BFC Range Booking Tool

Even though this is another booking tool similar to above this has a few key differences, which makes the code for this project very different.

Project Three Image

J6 Tasking Tool

This is very different to the previous 2 applications, technical wise it is more advanced but I'm not happy with it visually and I have significantly improved on this shown in the above projects.

Project Four Image

Carriage Certificate

The user interface is on the Tasking Tool above but this project is primarily to display the technical flow required to automate this task.

Project Four Image

Outage Tracker

The user interface is also on the Tasking Tool shown above but this is as a seperate project as it was created some time afterwards but was added on for centralisation purposes.

Project Four Image

Task Tracker

This is also a bolt on for the Tasking Tool project, but this is used by the staff rather than customers and has some changes I thought mentioning.

BFC Station Visits Application

Click to expand
Project Image
Opening Screen

Upon launching the application, users are greeted by the questions used for the request. This design choice was made with user convenience in mind, ensuring that users have immediate access to the necessary fields while still retaining the option to navigate to other sections using the buttons, with administrative buttons only visible to those on the admin list these are located in the top right corner.


The dynamic nature of the questions is a key feature to ensure the user inputs the least amount of information required for their desired request, certain questions become visible based on the user's responses to previous questions.


Each section is clearly delineated for easy navigation, with mandatory fields to guide users on providing essential information. Users are promptly alerted to any missing or incorrect information, ensuring a smooth and error-free completion process.

Click to expand
Project Image
Questions

In this image showcasing the questions page, the approving officer is presented with a specific dropdown menu tailored to pull individuals' profiles exclusively from our global address list.


This custom feature serves to enhance accuracy and reduce the potential for user errors. Additionally, a designated section is provided for attaching necessary documentation to the user's request.


Should a user lack the required documentation at the time of submission, they have the option to proceed with the request by leaving this section blank. Subsequently, users can revisit the request in the user area to upload the document, triggering a notification to the bookings team.


I have included below the code for the submit button, which encompasses error handling, information transfer mechanisms, mandatory field validations, and more.





If(PageNo = 1,

If(rdoQuestion12_3.SelectedText.Value <> "Staff Clearance",

If(
    IsBlank(ComboBox1_10.SelectedItems) Or
    IsBlank(txtQuestion2.Text) Or
    IsBlank(txtQuestion3.Text) Or
    IsBlank(txtQuestion4.Text) Or
    IsBlank(txtQuestion5.Text) Or
    IsBlank(txtQuestion6.Text) Or
    IsBlank(txtQuestion7.Text) Or
    IsBlank(txtQuestion8.Text) Or
    IsBlank(txtQuestion10.Text) Or
    IsBlank(txtQuestion11.Text) Or
    IsBlank(rdoQuestion12_3.Selected.Value) Or
    IsBlank(rdoQuestion12_2.Selected.Value) Or
    Checkbox1.Value = false,
    
        UpdateContext({EmptyError: true}),

  If(rdoQuestion12_2.SelectedText.Value = "No", 
        If(IsBlank(ComboBox1_13.SelectedItems), UpdateContext({EmptyError: false}); UpdateContext({AppErrorMessage: true}), 
        If(IsBlank(ComboBox1_12.SelectedItems), UpdateContext({EmptyError: false}); UpdateContext({AppErrorMessage: false}); UpdateContext({AuthErrorMessage: true}),

        UpdateContext({EmptyError: false});
        UpdateContext({AppErrorMessage: false});
        UpdateContext({AuthErrorMessage: false});
        UpdateContext({SubmitPopup: true});
        UpdateContext({CancelNotif: true});
        UpdateContext({varLoadingError: false});
        
If(IsError(
                Set(varID, 
        'BFCStationVisits-PatchVARP/Intra'.Run(
            ComboBox1_10.Selected.Mail,
            txtQuestion2.Text,
            txtQuestion3.Text,
            txtQuestion4.Text,
            txtQuestion5.Text,
            txtQuestion6.Text,
            txtQuestion7.Text,
            txtQuestion8.Text,
            txtQuestion9.Text,
            txtQuestion10.Text,
            txtQuestion11.Text,
            rdoQuestion12_3.Selected.Value, 
          If(rdoQuestion12_2.SelectedText.Value= "No", ComboBox1_13.Selected.Mail, ComboBox1_10.Selected.Mail),
          If(rdoQuestion12_2.SelectedText.Value= "No", ComboBox1_12.Selected.Value, ComboBox1_10.Selected.Mail),
           rdoQuestion12_2.SelectedText.Value,
           ComboBox1_12.Selected.Role
                ).id);

If(!IsEmpty(DataCardValue31.Attachments),
        'BFCStationVisits-Attachments'.Run(
            varID,
            {file:{
            contentBytes: First(DataCardValue31.Attachments).Value,
            name: First(DataCardValue31.Attachments).Name}})
        )),

UpdateContext({ConfPopUp: true});UpdateContext({varLoadingError: true}),
UpdateContext({ConfPopUp: true}))
        
)))),



If(
    IsBlank(ComboBox1_10.SelectedItems) Or
    IsBlank(txtQuestion2.Text) Or
    IsBlank(txtQuestion3.Text) Or
    IsBlank(txtQuestion4.Text) Or
    IsBlank(txtQuestion5.Text) Or
    IsBlank(txtQuestion6.Text) Or
    IsBlank(txtQuestion7.Text) Or
    IsBlank(txtQuestion8.Text) Or
    IsBlank(txtQuestion10.Text) Or
    IsBlank(txtQuestion11.Text) Or
    IsBlank(rdoQuestion12_3.SelectedText.Value) Or
    IsBlank(rdoQuestion12.Selected.Value) Or
    IsBlank(dtpQuestion13_1.SelectedDate) Or
    IsBlank(dtpQuestion13_2.SelectedDate) Or
    IsBlank(dtpQuestion14_1.SelectedDate) Or
    IsBlank(dtpQuestion14_2.SelectedDate) Or
    IsBlank(dtpQuestion15_1.SelectedDate) Or
    IsBlank(dtpQuestion15_2.SelectedDate) Or
    Checkbox1.Value = false,
        UpdateContext({EmptyError: true}),

        UpdateContext({ScrollReset2: true});UpdateContext({ScrollReset1: true});UpdateContext({EmptyError: false})
)),

If(
    IsBlank(txtRow2.Text) Or
    IsBlank(txtRow3.Text) Or
    IsBlank(DtpRow4.SelectedDate) Or
    IsBlank(txtRow5.Text) Or
    IsBlank(txtRow6.Text) Or
    IsBlank(txtRow7.Text) Or
    IsBlank(txtRow8.Text) Or
    IsBlank(txtRow9.Text) Or
    IsBlank(txtRow10.Text) Or
    IsBlank(txtRow11.Text) Or
    IsBlank(rdoQuestion12_2) Or
    IsBlank(ChkQuestion17.Value) Or
    IsBlank(ChkQuestion17_1.Value) Or
    IsBlank(ChkQuestion17_2.Value) Or
    IsBlank(ChkQuestion17_3.Value) Or
    IsBlank(ChkQuestion17_4.Value) Or
    IsBlank(txtQuestion18.Text) Or
    IsBlank(txtQuestion19.Text) Or
    IsBlank(txtQuestion20.Text) Or

    If(!IsBlank(txtRow2_1.Text),
    IsBlank(txtRow3_1.Text) Or
    IsBlank(DtpRow4_1.SelectedDate) Or
    IsBlank(txtRow5_1.Text) Or
    IsBlank(txtRow6_1.Text) Or
    IsBlank(txtRow7_1.Text) Or
    IsBlank(txtRow8_1.Text) Or
    IsBlank(txtRow9_1.Text) Or
    IsBlank(txtRow10_1.Text) Or
    IsBlank(txtRow11_1.Text)
    ) Or 
    If(!IsBlank(txtRow2_2.Text),
    IsBlank(txtRow3_2.Text) Or
    IsBlank(DtpRow4_2.SelectedDate) Or
    IsBlank(txtRow5_2.Text) Or
    IsBlank(txtRow6_2.Text) Or
    IsBlank(txtRow7_2.Text) Or
    IsBlank(txtRow8_2.Text) Or
    IsBlank(txtRow9_2.Text) Or
    IsBlank(txtRow10_2.Text) Or
    IsBlank(txtRow11_2.Text)
    ) Or 
    If(!IsBlank(txtRow2_3.Text),
    IsBlank(txtRow3_3.Text) Or
    IsBlank(DtpRow4_3.SelectedDate) Or
    IsBlank(txtRow5_3.Text) Or
    IsBlank(txtRow6_3.Text) Or
    IsBlank(txtRow7_3.Text) Or
    IsBlank(txtRow8_3.Text) Or
    IsBlank(txtRow9_3.Text) Or
    IsBlank(txtRow10_3.Text) Or
    IsBlank(txtRow11_3.Text)
    ) Or 
    If(!IsBlank(txtRow2_4.Text),
    IsBlank(txtRow3_4.Text) Or
    IsBlank(DtpRow4_4.SelectedDate) Or
    IsBlank(txtRow5_4.Text) Or
    IsBlank(txtRow6_4.Text) Or
    IsBlank(txtRow7_4.Text) Or
    IsBlank(txtRow8_4.Text) Or
    IsBlank(txtRow9_4.Text) Or
    IsBlank(txtRow10_4.Text) Or
    IsBlank(txtRow11_4.Text)
    ) Or 
    If(!IsBlank(txtRow2_5.Text),
    IsBlank(txtRow3_5.Text) Or
    IsBlank(DtpRow4_5.SelectedDate) Or
    IsBlank(txtRow5_5.Text) Or
    IsBlank(txtRow6_5.Text) Or
    IsBlank(txtRow7_5.Text) Or
    IsBlank(txtRow8_5.Text) Or
    IsBlank(txtRow9_5.Text) Or
    IsBlank(txtRow10_5.Text) Or
    IsBlank(txtRow11_5.Text)
    ) Or
    If(!IsBlank(txtRow2_6.Text),
    IsBlank(txtRow3_6.Text) Or
    IsBlank(DtpRow4_6.SelectedDate) Or
    IsBlank(txtRow5_6.Text) Or
    IsBlank(txtRow6_6.Text) Or
    IsBlank(txtRow7_6.Text) Or
    IsBlank(txtRow8_6.Text) Or
    IsBlank(txtRow9_6.Text) Or
    IsBlank(txtRow10_6.Text) Or
    IsBlank(txtRow11_6.Text)
    ) Or  
    If(!IsBlank(txtRow2_7.Text),
    IsBlank(txtRow3_7.Text) Or
    IsBlank(DtpRow4_7.SelectedDate) Or
    IsBlank(txtRow5_7.Text) Or
    IsBlank(txtRow6_7.Text) Or
    IsBlank(txtRow7_7.Text) Or
    IsBlank(txtRow8_7.Text) Or
    IsBlank(txtRow9_7.Text) Or
    IsBlank(txtRow10_7.Text) Or
    IsBlank(txtRow11_7.Text)
    ) Or 
        If(!IsBlank(txtRow2_8.Text),
    IsBlank(txtRow3_8.Text) Or
    IsBlank(DtpRow4_8.SelectedDate) Or
    IsBlank(txtRow5_8.Text) Or
    IsBlank(txtRow6_8.Text) Or
    IsBlank(txtRow7_8.Text) Or
    IsBlank(txtRow8_8.Text) Or
    IsBlank(txtRow9_8.Text) Or
    IsBlank(txtRow10_8.Text) Or
    IsBlank(txtRow11_8.Text)
    ),
        UpdateContext({EmptyError: true}),

        If(rdoQuestion12_2.SelectedText.Value = "No", 
        If(IsBlank(ComboBox1_13.SelectedItems), UpdateContext({EmptyError: false}); UpdateContext({AppErrorMessage: true}), 
        If(IsBlank(ComboBox1_12.SelectedItems), UpdateContext({EmptyError: false}); UpdateContext({AppErrorMessage: false}); UpdateContext({AuthErrorMessage: true}),

        UpdateContext({EmptyError: false});
        UpdateContext({AppErrorMessage: false});
        UpdateContext({AuthErrorMessage: false});
        UpdateContext({SubmitPopup: true});
        UpdateContext({CancelNotif: true});
        UpdateContext({varLoadingError: false});

        If(IsError(
                Set(varID, 
        'BFCStationVisits-Patch'.Run(
            ComboBox1_10.Selected.Mail,
            txtQuestion2.Text,
            txtQuestion3.Text,
            txtQuestion4.Text,
            txtQuestion5.Text,
            txtQuestion6.Text,
            txtQuestion7.Text,
            txtQuestion8.Text,
            txtQuestion9.Text,
            txtQuestion10.Text,
            txtQuestion11.Text,
            rdoQuestion12.Selected.Value, 
            Text(dtpQuestion13_1.SelectedDate, "yyyy-mm-dd"),
            Text(dtpQuestion13_2.SelectedDate, "yyyy-mm-dd"),
            Text(dtpQuestion14_1.SelectedDate, "yyyy-mm-dd"),
            Text(dtpQuestion14_2.SelectedDate, "yyyy-mm-dd"),
            Text(dtpQuestion15_1.SelectedDate, "yyyy-mm-dd"),
            Text(dtpQuestion15_2.SelectedDate, "yyyy-mm-dd")).ID);
            
        'BFCStationVisits-Patch2'.Run(
        Concatenate(If(ChkQuestion17.Value = true, "Akrotiri, "), If(ChkQuestion17_1.Value = true, "Episkopi, "), If(ChkQuestion17_2.Value = true, "Dhekelia, "), If(ChkQuestion17_3.Value = true, "Ayios Nikolaos, "), If(ChkQuestion17_4.Value = true, "TDS/OLY")),
        txtQuestion18.Text,
        txtQuestion19.Text,
        txtQuestion20.Text,
        varID,
        Concatenate(txtRow2.Text, " | ", txtRow3.Text, " | ", DtpRow4.SelectedDate, " | ", txtRow5.Text, " | ", txtRow11_18.Text, " | ", txtRow6.Text, " | ", txtRow7.Text, " | ", txtRow8.Text, " | ", txtRow9.Text, " | ", txtRow10.Text, " | ", txtRow11.Text),
        If(!IsBlank(txtRow2_1.Text), Concatenate(txtRow2_1.Text, " | ", txtRow3_1.Text, " | ", DtpRow4_1.SelectedDate, " | ", txtRow5_1.Text, " | ", txtRow11_19.Text, " | ", txtRow6_1.Text, " | ", txtRow7_1.Text, " | ", txtRow8_1.Text, " | ", txtRow9_1.Text, " | ", txtRow10_1.Text, " | ", txtRow11_1.Text), "N/A"),
        If(!IsBlank(txtRow2_2.Text), Concatenate(txtRow2_2.Text, " | ", txtRow3_2.Text, " | ", DtpRow4_2.SelectedDate, " | ", txtRow5_2.Text, " | ", txtRow11_20.Text, " | ", txtRow6_2.Text, " | ", txtRow7_2.Text, " | ", txtRow8_2.Text, " | ", txtRow9_2.Text, " | ", txtRow10_2.Text, " | ", txtRow11_2.Text), "N/A"),
        If(!IsBlank(txtRow2_3.Text), Concatenate(txtRow2_3.Text, " | ", txtRow3_3.Text, " | ", DtpRow4_3.SelectedDate, " | ", txtRow5_3.Text, " | ", txtRow11_21.Text, " | ", txtRow6_3.Text, " | ", txtRow7_3.Text, " | ", txtRow8_3.Text, " | ", txtRow9_3.Text, " | ", txtRow10_3.Text, " | ", txtRow11_3.Text), "N/A"),
        If(!IsBlank(txtRow2_4.Text), Concatenate(txtRow2_4.Text, " | ", txtRow3_4.Text, " | ", DtpRow4_4.SelectedDate, " | ", txtRow5_4.Text, " | ", txtRow11_22.Text, " | ", txtRow6_4.Text, " | ", txtRow7_4.Text, " | ", txtRow8_4.Text, " | ", txtRow9_4.Text, " | ", txtRow10_4.Text, " | ", txtRow11_4.Text), "N/A"),
        If(!IsBlank(txtRow2_5.Text), Concatenate(txtRow2_5.Text, " | ", txtRow3_5.Text, " | ", DtpRow4_5.SelectedDate, " | ", txtRow5_5.Text, " | ", txtRow11_23.Text, " | ", txtRow6_5.Text, " | ", txtRow7_5.Text, " | ", txtRow8_5.Text, " | ", txtRow9_5.Text, " | ", txtRow10_5.Text, " | ", txtRow11_5.Text), "N/A"),
        If(!IsBlank(txtRow2_6.Text), Concatenate(txtRow2_6.Text, " | ", txtRow3_6.Text, " | ", DtpRow4_6.SelectedDate, " | ", txtRow5_6.Text, " | ", txtRow11_24.Text, " | ", txtRow6_6.Text, " | ", txtRow7_6.Text, " | ", txtRow8_6.Text, " | ", txtRow9_6.Text, " | ", txtRow10_6.Text, " | ", txtRow11_6.Text), "N/A"),
        If(!IsBlank(txtRow2_7.Text), Concatenate(txtRow2_7.Text, " | ", txtRow3_7.Text, " | ", DtpRow4_7.SelectedDate, " | ", txtRow5_7.Text, " | ", txtRow11_25.Text, " | ", txtRow6_7.Text, " | ", txtRow7_7.Text, " | ", txtRow8_7.Text, " | ", txtRow9_7.Text, " | ", txtRow10_7.Text, " | ", txtRow11_7.Text), "N/A"),
        If(!IsBlank(txtRow2_8.Text), Concatenate(txtRow2_8.Text, " | ", txtRow3_8.Text, " | ", DtpRow4_8.SelectedDate, " | ", txtRow5_8.Text, " | ", txtRow11_26.Text, " | ", txtRow6_8.Text, " | ", txtRow7_8.Text, " | ", txtRow8_8.Text, " | ", txtRow9_8.Text, " | ", txtRow10_8.Text, " | ", txtRow11_8.Text), "N/A"),
        If(!IsBlank(dtpQuestion21_1.SelectedDate), Text(dtpQuestion21_1.SelectedDate, "yyyy-mm-dd"), Text(Today(), "yyyy-mm-dd")),
        If(!IsBlank(dtpQuestion21_2.SelectedDate), Text(dtpQuestion21_2.SelectedDate, "yyyy-mm-dd"), Text(Today(), "yyyy-mm-dd")),
        If(rdoQuestion12_2.SelectedText.Value= "No", ComboBox1_13.Selected.Mail, ComboBox1_10.Selected.Mail),
        If(rdoQuestion12_2.SelectedText.Value= "No", ComboBox1_12.Selected.Value, ComboBox1_10.Selected.Mail),
        rdoQuestion12_2.SelectedText.Value,
        rdoQuestion12_3.Selected.Value,
        ComboBox1_12.Selected.Role
        );

If(!IsEmpty(DataCardValue31.Attachments),
        'BFCStationVisits-Attachments'.Run(
            varID,
            {file:{
            contentBytes: First(DataCardValue31.Attachments).Value,
            name: First(DataCardValue31.Attachments).Name}}))),

        UpdateContext({ConfPopUp: true});UpdateContext({varLoadingError: true}),
        UpdateContext({ConfPopUp: true}))
        
)),

        UpdateContext({EmptyError: false});
        UpdateContext({AppErrorMessage: false});
        UpdateContext({AuthErrorMessage: false});
        UpdateContext({SubmitPopup: true});
        UpdateContext({CancelNotif: true});
        UpdateContext({varLoadingError: false});

        If(IsError(
                Set(varID, 
        'BFCStationVisits-Patch'.Run(
            ComboBox1_10.Selected.Mail,
            txtQuestion2.Text,
            txtQuestion3.Text,
            txtQuestion4.Text,
            txtQuestion5.Text,
            txtQuestion6.Text,
            txtQuestion7.Text,
            txtQuestion8.Text,
            txtQuestion9.Text,
            txtQuestion10.Text,
            txtQuestion11.Text,
            rdoQuestion12.Selected.Value, 
            Text(dtpQuestion13_1.SelectedDate, "yyyy-mm-dd"),
            Text(dtpQuestion13_2.SelectedDate, "yyyy-mm-dd"),
            Text(dtpQuestion14_1.SelectedDate, "yyyy-mm-dd"),
            Text(dtpQuestion14_2.SelectedDate, "yyyy-mm-dd"),
            Text(dtpQuestion15_1.SelectedDate, "yyyy-mm-dd"),
            Text(dtpQuestion15_2.SelectedDate, "yyyy-mm-dd")).ID);
            
        'BFCStationVisits-Patch2'.Run(
        Concatenate(If(ChkQuestion17.Value = true, "Akrotiri, "), If(ChkQuestion17_1.Value = true, "Episkopi, "), If(ChkQuestion17_2.Value = true, "Dhekelia, "), If(ChkQuestion17_3.Value = true, "Ayios Nikolaos, "), If(ChkQuestion17_4.Value = true, "TDS/OLY")),
        txtQuestion18.Text,
        txtQuestion19.Text,
        txtQuestion20.Text,
        varID,
        Concatenate(txtRow2.Text, " | ", txtRow3.Text, " | ", DtpRow4.SelectedDate, " | ", txtRow5.Text, " | ", txtRow11_18.Text, " | ", txtRow6.Text, " | ", txtRow7.Text, " | ", txtRow8.Text, " | ", txtRow9.Text, " | ", txtRow10.Text, " | ", txtRow11.Text),
        If(!IsBlank(txtRow2_1.Text), Concatenate(txtRow2_1.Text, " | ", txtRow3_1.Text, " | ", DtpRow4_1.SelectedDate, " | ", txtRow5_1.Text, " | ", txtRow11_19.Text, " | ", txtRow6_1.Text, " | ", txtRow7_1.Text, " | ", txtRow8_1.Text, " | ", txtRow9_1.Text, " | ", txtRow10_1.Text, " | ", txtRow11_1.Text), "N/A"),
        If(!IsBlank(txtRow2_2.Text), Concatenate(txtRow2_2.Text, " | ", txtRow3_2.Text, " | ", DtpRow4_2.SelectedDate, " | ", txtRow5_2.Text, " | ", txtRow11_20.Text, " | ", txtRow6_2.Text, " | ", txtRow7_2.Text, " | ", txtRow8_2.Text, " | ", txtRow9_2.Text, " | ", txtRow10_2.Text, " | ", txtRow11_2.Text), "N/A"),
        If(!IsBlank(txtRow2_3.Text), Concatenate(txtRow2_3.Text, " | ", txtRow3_3.Text, " | ", DtpRow4_3.SelectedDate, " | ", txtRow5_3.Text, " | ", txtRow11_21.Text, " | ", txtRow6_3.Text, " | ", txtRow7_3.Text, " | ", txtRow8_3.Text, " | ", txtRow9_3.Text, " | ", txtRow10_3.Text, " | ", txtRow11_3.Text), "N/A"),
        If(!IsBlank(txtRow2_4.Text), Concatenate(txtRow2_4.Text, " | ", txtRow3_4.Text, " | ", DtpRow4_4.SelectedDate, " | ", txtRow5_4.Text, " | ", txtRow11_22.Text, " | ", txtRow6_4.Text, " | ", txtRow7_4.Text, " | ", txtRow8_4.Text, " | ", txtRow9_4.Text, " | ", txtRow10_4.Text, " | ", txtRow11_4.Text), "N/A"),
        If(!IsBlank(txtRow2_5.Text), Concatenate(txtRow2_5.Text, " | ", txtRow3_5.Text, " | ", DtpRow4_5.SelectedDate, " | ", txtRow5_5.Text, " | ", txtRow11_23.Text, " | ", txtRow6_5.Text, " | ", txtRow7_5.Text, " | ", txtRow8_5.Text, " | ", txtRow9_5.Text, " | ", txtRow10_5.Text, " | ", txtRow11_5.Text), "N/A"),
        If(!IsBlank(txtRow2_6.Text), Concatenate(txtRow2_6.Text, " | ", txtRow3_6.Text, " | ", DtpRow4_6.SelectedDate, " | ", txtRow5_6.Text, " | ", txtRow11_24.Text, " | ", txtRow6_6.Text, " | ", txtRow7_6.Text, " | ", txtRow8_6.Text, " | ", txtRow9_6.Text, " | ", txtRow10_6.Text, " | ", txtRow11_6.Text), "N/A"),
        If(!IsBlank(txtRow2_7.Text), Concatenate(txtRow2_7.Text, " | ", txtRow3_7.Text, " | ", DtpRow4_7.SelectedDate, " | ", txtRow5_7.Text, " | ", txtRow11_25.Text, " | ", txtRow6_7.Text, " | ", txtRow7_7.Text, " | ", txtRow8_7.Text, " | ", txtRow9_7.Text, " | ", txtRow10_7.Text, " | ", txtRow11_7.Text), "N/A"),
        If(!IsBlank(txtRow2_8.Text), Concatenate(txtRow2_8.Text, " | ", txtRow3_8.Text, " | ", DtpRow4_8.SelectedDate, " | ", txtRow5_8.Text, " | ", txtRow11_26.Text, " | ", txtRow6_8.Text, " | ", txtRow7_8.Text, " | ", txtRow8_8.Text, " | ", txtRow9_8.Text, " | ", txtRow10_8.Text, " | ", txtRow11_8.Text), "N/A"),
        If(!IsBlank(dtpQuestion21_1.SelectedDate), Text(dtpQuestion21_1.SelectedDate, "yyyy-mm-dd"), Text(Today(), "yyyy-mm-dd")),
        If(!IsBlank(dtpQuestion21_2.SelectedDate), Text(dtpQuestion21_2.SelectedDate, "yyyy-mm-dd"), Text(Today(), "yyyy-mm-dd")),
        If(rdoQuestion12_2.SelectedText.Value= "No", ComboBox1_13.Selected.Mail, ComboBox1_10.Selected.Mail),
        If(rdoQuestion12_2.SelectedText.Value= "No", ComboBox1_12.Selected.Value, ComboBox1_10.Selected.Mail),
        rdoQuestion12_2.SelectedText.Value,
        rdoQuestion12_3.Selected.Value,
        ComboBox1_12.Selected.Role
        );

If(!IsEmpty(DataCardValue31.Attachments),
        'BFCStationVisits-Attachments'.Run(
            varID,
            {file:{
            contentBytes: First(DataCardValue31.Attachments).Value,
            name: First(DataCardValue31.Attachments).Name}}))),

        UpdateContext({ConfPopUp: true});UpdateContext({varLoadingError: true}),
        UpdateContext({ConfPopUp: true}))

)))

Click to expand
Project Image
Error Handling

This image captures a crucial aspect of my project in PowerApps, showcasing the implementation of robust error handling mechanisms across various sections of the application.


By incorporating these processes, users are promptly notified when an action they attempt fails, ensuring transparency and user awareness. This strategic approach addresses past challenges encountered in my previous app developments, where errors occurred without user notification, leading to a lack of awareness regarding the failure of their requests.


While errors are infrequent occurrences, factors like network connectivity issues can trigger them, underscoring the critical role of error handling procedures in maintaining application functionality and user satisfaction.

Click to expand
Project Image
Admin Screen

In this image, you are presented with the administrative area, a pivotal space within the system where the bookings team gains visibility into all incoming requests. Here, they can track the progress of each request as it moves through the workflow stages.


Upon submission, a request seamlessly navigates its way to the approving and authorising officer, and potentially to HQ BFC and IGDN, contingent upon the user's input. This journey is facilitated through automated emails and approval notifications. Once responses are received, they are prominently displayed at the forefront of the ticket, as exemplified in the image.


Furthermore, the interface offers convenient functionalities accessible via the icon located in the top right corner of the screen. Users can swiftly archive, edit, or delete each booking with ease. Following any of these actions, users are promptly notified through update emails. A more detailed demonstration of this process will be showcased later when I delve into the Power Automate flow.

Click to expand
Project Image
Document Upload

Displayed here is the user area, closely mirroring the administrative section which is why this is focused soley on the attachment aspect, users have access solely to their own submitted requests from their individual accounts.


Users simply navigate to the upload file button, select their desired file from their computer, and seamlessly attach it to their request. The uploaded file becomes visible within the text box, enhancing the request's content.


Subsequently, the upload file button is automatically removed, streamlining the user experience.

Click to expand
Project Image
Permissions Screen

Some details are redacted for privacy and data protection. Despite this, the essential aspects of the image remain visible. The image serves as a central hub for managing permissions for staff members.


It enables the addition and removal of permissions for employees, as well as the ability to change incumbents within the system. This functionality empowers staff to dynamically adjust permissions and determine where automated emails are directed based on their assigned permissions. This dynamic system not only facilitates seamless permission management but also streamlines the process of updating personnel details.


In the long run, this system reduces the need for manual intervention from developers or the team, as it operates based on dynamic values rather than static configurations.

Click to expand
Project Image
Report an Issue

This screen captures the "Report an Issue" feature within this particular PowerApp. Users can easily submit requests in case of any encountered issues through this interface. Once submitted, the request is automatically stored in our error handling database, which serves as a central hub linked to all our individual PowerApps.


Simultaneously, an automated email notification is triggered to alert the team about the submitted issue/error. Upon resolution of the reported issue, a simple click on the "Resolve" button in the automated email triggers a notification to the user, confirming the resolution and saving the error details in our storage for future reference.


This method not only ensures efficient issue resolution but also archives the steps taken to address the problem, providing valuable insights for similar situations in the future.

Click to expand
Project Image
Power Automate Flow

In this zoomed-out image, the intricate details of the project may not be immediately apparent, but specific aspects have been highlighted through zoomed-in sections. When a booking is initiated, the flow efficiently stores the relevant information in the data source. Subsequently, a visually appealing confirmation email is automatically generated and sent to the user. Noteworthy is the incorporation of HTML elements to craft this aesthetically pleasing email, showcasing a proficiency gained during the project's development, as depicted in the image.


The flow is designed to incorporate conditional logic, enabling the system to dynamically adjust its actions based on the user inputs, for example a 1* visitor would lead to the generation of an approvals email sent to HQ BFC for necessary approval. Subsequent actions are determined by the outcome, ensuring that all stakeholders previously outlined in the admin access image receive pertinent information promptly.


This meticulous flow guarantees that the right individuals receive accurate information at the appropriate junctures, streamlining processes and minimising human intervention. By automating tasks that would traditionally require manual effort, such as individual email communications, the system significantly enhances efficiency. This automation not only reduces the margin for error but also optimises resource allocation, ultimately saving valuable time for personnel who would otherwise be engaged in laborious manual tasks.

Extra Image 1 Extra Image 2 Extra Image 3
Click to expand
Project Image
HTML Confirmation Emails

As demonstrated in the example above, this is one of the automated confirmation emails that users receive upon successfully submitting a booking. The email serves to notify them that their request has been received by the team and is currently being processed.


All of the automated emails generated throughout the submission workflow—outlined in the Power Automate card—follow a consistent structure and visual layout to ensure a clear and professional user experience.


To achieve this level of presentation, I taught myself the basics of HTML, which allowed me to customise and enhance the appearance of the emails beyond default formatting. I later built upon that foundational knowledge to design and develop this very website, showcasing how I've applied and expanded my technical skills across different parts of the project.


Below is the HTML code used for generating one of the numerous emails dispatched through Power Automate.




<!DOCTYPE html>
<html lang="en" dir="ltr" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" style="color-scheme:light dark;supported-color-schemes:light dark;">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1 user-scalable=yes">
<meta name="format-detection" content="telephone=no, date=no, address=no, email=no, url=no">
<meta name="x-apple-disable-message-reformatting">
<meta name="color-scheme" content="light dark">
<meta name="supported-color-schemes" content="light dark">
<title></title>
<!--[if mso]> <noscript><xml><o:OfficeDocumentSettings><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml></noscript>
<![endif]-->
<!--[if mso]>
<style>table,tr,td,p,span,a{mso-line-height-rule:exactly !important;line-height:120% !important;mso-table-lspace:0 !important;mso-table-rspace:0 !important;}.mso-padding{padding-top:20px !important;padding-bottom:20px !important;}
</style>
<![endif]-->
<style>a[x-apple-data-detectors]{color:inherit!important;text-decoration:none!important;font-size:inherit!important;font-family:inherit!important;font-weight:inherit!important;line-height:inherit!important;}u+#body a{color:inherit!important;text-decoration:none!important;font-size:inherit!important;font-family:inherit!important;font-weight:inherit!important;line-height:inherit!important;}#MessageViewBody a{color:inherit!important;text-decoration:none!important;font-size:inherit!important;
font-family:inherit!important;font-weight:inherit!important;line-height:inherit!important;}:root{color-scheme:light dark;supported-color-schemes:light dark;}tr{vertical-align:middle;}p,a,li{color:#000000;font-size:16px;mso-line-height-rule:exactly;line-height:24px;font-family:Arial,sans-serif;}p:first-child{margin-top:0!important;}p:last-child{margin-bottom:0!important;}a{text-decoration:underline;font-weight:bold;color:#0000ff}.alert p{vertical-align:top;color:#fff;font-weight:500;text-align:
center;border-radius:3px 3px 0 0;background-color:#FF9F00;margin:0;padding:20px;}@media only screen and (max-width:599px){.full-width-mobile{width:100%!important;height:auto!important;}.mobile-padding{padding-left:10px!important;padding-right:10px!important;}.mobile-stack{display:block!important;width:100%!important;}}@media (prefers-color-scheme:dark){body,div,table,td{background-color:#000000!important;color:#ffffff!important;}.content{background-color:#222222!important;}p,li,.white-text{color:#B3BDC4!important;}a{color:#84cfe2!important;}a span,.alert-dark p{color:#ffffff!important;}}
</style>
</head>
<body class="body" style="background-color:#f4f4f4;"><div style="display:none;font-size:1px;color:#f4f4f4;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;"></div> <span style="display:none!important;visibility:hidden;mso-hide:all;font-size:1px;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;"> &nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;</span><div role="article" aria-roledescription="email" aria-label="Your Email" lang="en" dir="ltr" style="font-size:16px;font-size:1rem;font-size:max(16px,1rem);background-color:#f4f4f4;">
<table align="center" role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse:collapse;max-width:600px;width:100%;background-color:#f4f4f4;"><tr style="vertical-align:middle;" valign="middle"><td>
<!--[if mso]>
<table align="center" role="presentation" border="0" cellpadding="0" cellspacing="0" width="600" style="border-collapse:collapse;"><tr><td align="center">
<!--<![endif]-->
</td></tr><tr style="vertical-align:middle;" valign="middle"><td align="center">
<table align="center" role="presentation" border="0" cellpadding="0" cellspacing="0" width="600" style="border-collapse:collapse;max-width:600px;width:100%;background-color:#fffffe;"><tr style="vertical-align:middle;" valign="middle"><td>
<table align="center" role="presentation" border="0" cellpadding="0" cellspacing="0" width="600" style="border-collapse:collapse;max-width:600px;width:100%;"><tr style="vertical-align:middle;" valign="middle"><td class="mso-padding alert alert-warning alert-dark" align="center" bgcolor="#008000" valign="top"><p style="font-size:16px;mso-line-height-rule:exactly;line-height:24px;font-family:Arial,sans-serif;vertical-align:top;color:#fff;font-weight:500;text-align:center;border-radius:3px 3px 0 0;background-color:#008000margin:0;padding:20px;margin-top:0!important;margin-bottom:0!important;">BFC Station Booking App Notification.</p>
</td></tr></table>
</td></tr><tr style="vertical-align:middle;" valign="middle"><td align="center" style="padding:30px;" class="content">
<table align="center" role="presentation" border="0" cellpadding="0" cellspacing="0" width="600" style="border-collapse:collapse;max-width:600px;width:100%;background-color:#fffffe;"><tr style="vertical-align:middle;" valign="middle"><td class="content"><p style="color:#000000;font-size:16px;mso-line-height-rule:exactly;line-height:24px;font-family:Arial,sans-serif;margin-top:0!important;">You&nbsp;have <strong>atleast 1 </strong>booking awaiting action.</p><p style="color:#000000;font-size:16px;mso-line-height-rule:exactly;line-height:24px;font-family:Arial,sans-serif;margin-bottom:0!important;">Booking @{triggerBody()?['number']} has been authorised by the authorising officer @{outputs('Get_booking_item_2')?['body/AuthorisingOfficer/DisplayName']}, the booking information can be found below and also via the booking tool accessable via the button.</p>
<p style="color:#000000;font-size:16px;mso-line-height-rule:exactly;line-height:24px;font-family:Arial,sans-serif;margin-bottom:0!important;">

@{outputs('HTML_Table')}

</p>
</td></tr></table>
<tr style="vertical-align:middle;" valign="middle"><td align="center" class="content">
<table role="presentation" border="0" cellspacing="0" cellpadding="0" style="border-collapse:collapse;width:100%"><tr style="vertical-align:middle;" valign="middle"><td align="left" style="padding:0 0 0 30px;" class="content"><a href="https://apps.powerapps.com/play/e/881c8612-900a-4fe6-b210-deb6e5376b73/a/0da6e7ae-b2e7-4132-b6bb-5a4b870386f0?tenantId=be7760ed-5953-484b-ae95-d0a16dfa09e5&sourcetime=1732774734351#" style="font-size:16px;mso-line-height-rule:exactly;line-height:24px;font-family:Arial,sans-serif;font-weight:bold;background:#008000;text-decoration:none;padding:15px 25px;color:#fff;border-radius:4px;display:inline-block;mso-padding-alt:0;text-underline-color:#008000;" class="dark-button">
<!--[if mso]><i style="letter-spacing:25px;mso-font-width:-100%;mso-text-raise:30pt" hidden>&nbsp;</i>
<![endif]--><span style="mso-text-raise:15pt;">Station Booking App</span>
<!--[if mso]><i style="letter-spacing:25px;mso-font-width:-100%" hidden>&nbsp;</i>
<![endif]--></a>
</td></tr></table>
</td></tr><tr style="vertical-align:middle;" valign="middle"><td align="center" style="padding:30px;" class="content">
<table align="center" role="presentation" border="0" cellpadding="0" cellspacing="0" width="600" style="border-collapse:collapse;max-width:600px;width:100%;background-color:#fffffe;"><tr style="vertical-align:middle;" valign="middle"><td class="content"><p style="color:#000000;font-size:16px;mso-line-height-rule:exactly;line-height:24px;font-family:Arial,sans-serif;margin-top:0!important;margin-bottom:0!important;"></p>
</td></tr></table>
</td></tr></table>
<table align="center" role="presentation" border="0" cellpadding="0" cellspacing="0" width="600" style="border-collapse:collapse;max-width:600px;width:100%;"><tr style="vertical-align:middle;" valign="middle"><td align="center" style="padding:30px 0;"><p style="mso-line-height-rule:exactly;line-height:24px;font-family:Arial,sans-serif;font-size:14px;color:#999;margin-top:0!important;margin-bottom:0!important;"> DO NOT</a> reply to this email, no action will be taken!</p>
</td></tr></table>
</td></tr>
<!--[if mso]>
</td></tr></table>
<!--<![endif]--></table></div>
</body>
</html>

BFC Range Booking Tool

Click to expand
Project Image
Main Menu

The image showcases the primary menu of the BFC Range booking tool, designed for reserving various ranges throughout Cyprus.


Given the diverse range of locations available for users to select, I opted for a straightforward and uncluttered main menu to enhance the initial user experience upon entering the application.

Click to expand
Project Image
Range Booking Screen

Displayed in the image is the booking creation page for the range, where users input all essential booking details.


A notable feature distinguishing this project is its capability to generate error messages if a user attempts to book the same time, date, and range as another existing booking. Below, you can observe the code responsible for implementing this functionality.


I have included below the code for the submit button, which encompasses error handling, information transfer mechanisms, mandatory field validations, and more.





If(DataCardValue31.Visible = true And IsEmpty(DataCardValue31.Attachments) And IsEmpty(DataCardValue31_1.Attachments) Or
DataCardValue31.Visible = true And IsEmpty(DataCardValue31.Attachments) And !IsEmpty(DataCardValue31_1.Attachments) Or
DataCardValue31.Visible = true And !IsEmpty(DataCardValue31.Attachments) And IsEmpty(DataCardValue31_1.Attachments)
,

Notify("Make sure you attach the required documents when on overtime otherwise you will not be able to submit!", NotificationType.Error),

Set(varBookings, LookUp('BFC Range Booking Tool - Bookings',

RangeComplex = Radio2_5.SelectedText.Value And 
ComplexArea1 = varComplexArea1 And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) <= 'StartDate&Time' And 
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) >='EndDate&Time' Or

RangeComplex = Radio2_5.SelectedText.Value And
ComplexArea2 = varComplexArea2 And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) <= 'StartDate&Time' And 
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) >='EndDate&Time' Or

RangeComplex = Radio2_5.SelectedText.Value And
ComplexArea3 = varComplexArea3 And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) <= 'StartDate&Time' And 
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) >='EndDate&Time' Or

RangeComplex = Radio2_5.SelectedText.Value And
ComplexArea4 = varComplexArea4 And
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) <= 'StartDate&Time' And 
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) >='EndDate&Time' Or



RangeComplex = Radio2_5.SelectedText.Value And 
ComplexArea1 = varComplexArea1 And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) <= 'StartDate&Time' And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) >='EndDate&Time' And
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) <='EndDate&Time' Or

RangeComplex = Radio2_5.SelectedText.Value And 
ComplexArea2 = varComplexArea2 And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) <= 'StartDate&Time' And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) >='EndDate&Time' And
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) <='EndDate&Time' Or

RangeComplex = Radio2_5.SelectedText.Value And 
ComplexArea3 = varComplexArea3 And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) <= 'StartDate&Time' And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) >='EndDate&Time' And
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) <='EndDate&Time' Or

RangeComplex = Radio2_5.SelectedText.Value And 
ComplexArea4 = varComplexArea4 And
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) <= 'StartDate&Time' And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) >='EndDate&Time' And
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) <='EndDate&Time' Or



RangeComplex = Radio2_5.SelectedText.Value And 
ComplexArea1 = varComplexArea1 And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) >= 'StartDate&Time' And 
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) <='EndDate&Time' Or

RangeComplex = Radio2_5.SelectedText.Value And 
ComplexArea2 = varComplexArea2 And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) >= 'StartDate&Time' And 
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) <='EndDate&Time' Or

RangeComplex = Radio2_5.SelectedText.Value And 
ComplexArea3 = varComplexArea3 And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) >= 'StartDate&Time' And 
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) <='EndDate&Time' Or

RangeComplex = Radio2_5.SelectedText.Value And 
ComplexArea4 = varComplexArea4 And
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) >= 'StartDate&Time' And 
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) <='EndDate&Time' Or



RangeComplex = Radio2_5.SelectedText.Value And 
ComplexArea1 = varComplexArea1 And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) >= 'StartDate&Time' And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) <= 'EndDate&Time' And 
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) >='EndDate&Time' Or

RangeComplex = Radio2_5.SelectedText.Value And 
ComplexArea2 = varComplexArea2 And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) >= 'StartDate&Time' And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) <= 'EndDate&Time' And 
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) >='EndDate&Time' Or

RangeComplex = Radio2_5.SelectedText.Value And 
ComplexArea3 = varComplexArea3 And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) >= 'StartDate&Time' And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) <= 'EndDate&Time' And 
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) >='EndDate&Time' Or
    
RangeComplex = Radio2_5.SelectedText.Value And 
ComplexArea4 = varComplexArea4 And
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) >= 'StartDate&Time' And 
    DateTimeValue(sDate.SelectedDate & " " & sTime.SelectedText.myTime) <= 'EndDate&Time' And 
    DateTimeValue(eDate.SelectedDate & " " & eTime.SelectedText.myTime) >='EndDate&Time' 
));

If(!IsBlank(ComboBox1_11.Selected.Mail), 
If(ComboBox1_9.Visible = true And !IsBlank(ComboBox1_9.Selected.Mail) Or ComboBox1_9.Visible = false,

If(IsBlank(varBookings) Or Radio2_6.SelectedText.Value = "Yes",

If(Radio2_6.SelectedText.Value = "Yes" And IsEmpty(DataCardValue31_2.Attachments), Notify("Please make sure you've attached a screenshot showing proof that this booking has been deconflicted.",NotificationType.Warning),

If(IsError(

UpdateContext({AttachID:
Patch('BFC Range Booking Tool - Bookings',
Defaults('BFC Range Booking Tool - Bookings'),
{
MODNetEmail: ComboBox1_11.Selected.Mail,
Rank: TextInput2_55.Text,
Role: TextInput2_56.Text,
ContactNo: TextInput2_57.Text,
'BFCUnit?': Radio2_3.Selected.Value,
'Unit/Coy': TextInput2_58.Text,
OperationName: TextInput2_67.Text,
UIN: TextInput2_59.Text,
RangeComplex: Radio2_5.Selected.Value,
ComplexArea1: varComplexArea1,
ComplexArea2: varComplexArea2,
ComplexArea3: varComplexArea3,
ComplexArea4: varComplexArea4,
ActivityDesc: TextInput2_66.Text,
'StartDate&Time': sDate.SelectedDate + TimeValue(sTime.SelectedText.Value),
'EndDate&Time': eDate.SelectedDate + TimeValue(eTime.SelectedText.Value),
ShareRange: Radio2_6.Selected.Value,
BudgetHolder: ComboBox1_9.Selected.Mail,
OvertimeDetails: TextInput2_68.Text
}).ID});

If(!IsEmpty(DataCardValue31.Attachments) And !IsEmpty(DataCardValue31_1.Attachments),
'BFC-RangeBookingTool-Attachments'.Run(
    AttachID,
         {file:{
         contentBytes: First(DataCardValue31.Attachments).Value,
         name: First(DataCardValue31.Attachments).Name
         },
        file_1:{
         contentBytes: First(DataCardValue31_1.Attachments).Value,
         name: First(DataCardValue31_1.Attachments).Name
         }}
));

If(!IsEmpty(DataCardValue31_2.Attachments),
'BFCRangeBookingTool-ConflictionEmail'.Run(
    AttachID,
         {file:{
         contentBytes: First(DataCardValue31_2.Attachments).Value,
         name: First(DataCardValue31_2.Attachments).Name
         }}
))),
Notify("There was an error when trying to submit your booking request, please try again!",NotificationType.Error),
UpdateContext({SubmitPopup: true});
)),


Notify("Conflict - The following are already booked:" & 
If(varBookings.RangeComplex = "Akrotiri Range Complex" And varBookings.ComplexArea1 = "ETR", " ETR,", 
If(varBookings.RangeComplex = "Dhekelia Range Complex" And varBookings.ComplexArea1 = "A Range", " A Range,", 
If(varBookings.RangeComplex = "Pyla Range Complex" And varBookings.ComplexArea1 = "IBSR", " IBSR,"
))) &
If(varBookings.RangeComplex = "Akrotiri Range Complex" And varBookings.ComplexArea2 = "GroupingZeroing", " Grouping & Zeroing,", 
If(varBookings.RangeComplex = "Dhekelia Range Complex" And varBookings.ComplexArea2 = "B Range", " B Range,", 
If(varBookings.RangeComplex = "Pyla Range Complex" And varBookings.ComplexArea2 = "ICQB", " ICQB,"
))) &
If(varBookings.RangeComplex = "Akrotiri Range Complex" And varBookings.ComplexArea3 = "MMTR", " MMTR,", 
If(varBookings.RangeComplex = "Dhekelia Range Complex" And varBookings.ComplexArea3 = "25M", " 25M,", 
If(varBookings.RangeComplex = "Pyla Range Complex" And varBookings.ComplexArea3 = "LFTTA", " LFTTA,"
))) &
If(varBookings.RangeComplex = "Akrotiri Range Complex" And varBookings.ComplexArea4 = "CQB", " CQB,", 
If(varBookings.RangeComplex = "Dhekelia Range Complex" And varBookings.ComplexArea4 = "100M", " 100M,", 
If(varBookings.RangeComplex = "Pyla Range Complex" And varBookings.ComplexArea4 = "UGL", " UGL,"
))) &
" on " &
Left(varBookings.'StartDate&Time',10) & " for " & Right(varBookings.'StartDate&Time',5) & " to " & Left(varBookings.'EndDate&Time',10) & " until " & Right(varBookings.'EndDate&Time',5) & ". Please select another date and/or location."
, NotificationType.Error);
),
UpdateContext({ShowErrorBudget: true});
Notify("Some information has been incorrectly entered, please scroll up to the question for further information!", NotificationType.Error)),

UpdateContext({ShowError: true});
Notify("Some information has been incorrectly entered, please scroll up to the question for further information!", NotificationType.Error))
)

Click to expand
Project Image
FTA Booking Screen

I'm showcasing a specific section of the FTA booking area in order to highlight the presence of various training sectors within each training area, each one of these do not allow for double booking, unless deconfliction has been carried out.


Additionally, certain sectors are visibly greyed out, a topic we will delve into further in another section of the project.

Click to expand
Project Image
Calendar View

Regrettably, I had to extensively censor specific details on this image. Nevertheless, the calendar layout remains visible, showcasing the user's access to view all existing bookings.


This feature enables users to determine the optimal timing for booking their range slots. The calendar is colour-coded, with each range assigned a distinct colour. Red indicates closure for a particular range on specific days.


The below code generates the collection used by the calendar galleries, filtering the data source to include only the bookings relevant to the currently selected month. Each time the user navigates to a new month, the collection is cleared and repopulated with fresh data based on dynamic inputs. This ensures that only the necessary information for the selected month is retrieved, keeping the app responsive and efficient.




UpdateContext({FullCalendar: !FullCalendar});
UpdateContext({Bookings: "All"});

Set(varCalendarDate, DateValue("1" & "/" & Month(Today()) & "/" & Year(Today())));
Set(varCalendarFirstDayView, DateAdd(varCalendarDate, - Weekday(varCalendarDate, StartOfWeek.Monday), TimeUnit.Days));
Set(varCalendarFirstDayNextMonth, DateAdd(DateAdd(varCalendarDate, 1, TimeUnit.Months), 7 - Weekday(DateAdd(varCalendarDate, 1, TimeUnit.Months)), TimeUnit.Days));


ClearCollect(ColCalendar, Filter('BFC Range Booking Tool - Bookings', ('StartDate&Time' > varCalendarFirstDayView And 'StartDate&Time' <= varCalendarFirstDayNextMonth) Or ('EndDate&Time' > varCalendarFirstDayView And 'EndDate&Time' <= varCalendarFirstDayNextMonth) Or ('StartDate&Time' <= varCalendarFirstDayView And 'EndDate&Time' > varCalendarFirstDayNextMonth)));


Collect(ColCalendar, Filter('BFC FTA Booking Tool - Bookings', ('StartDate&Time' > varCalendarFirstDayView And 'StartDate&Time' <= varCalendarFirstDayNextMonth) Or ('EndDate&Time' > varCalendarFirstDayView And 'EndDate&Time' <= varCalendarFirstDayNextMonth) Or ('StartDate&Time' <= varCalendarFirstDayView And 'EndDate&Time' > varCalendarFirstDayNextMonth)));


Despite the colour differentiation, navigating through numerous bookings can still be challenging. To address this, I incorporated filter options, empowering users to filter by dates, times, and locations for enhanced clarity and ease of use, this can be seen below.




SortByColumns(Filter(ColCalendar, 
Switch(Bookings, "All",

If(AkiRange_3.Value = true,
RangeComplex="Akrotiri Range Complex" And DateValue(StartDateTime) <= DateValue(lbl_CurrentDate_2.Text) And  DateValue(EndDateTime) >= DateValue(lbl_CurrentDate_2.Text) Or
DateValue(lbl_CurrentDate_2.Text) in ETR Or 
DateValue(lbl_CurrentDate_2.Text) in GroupingZeroing Or
DateValue(lbl_CurrentDate_2.Text) in MMTR Or 
DateValue(lbl_CurrentDate_2.Text) in CQB
) Or

If(DhekRange_3.Value = true,
RangeComplex="Dhekelia Range Complex" And DateValue(StartDateTime) <= DateValue(lbl_CurrentDate_2.Text) And  DateValue(EndDateTime) >= DateValue(lbl_CurrentDate_2.Text) Or
DateValue(lbl_CurrentDate_2.Text) in ARange Or 
DateValue(lbl_CurrentDate_2.Text) in BRange Or
DateValue(lbl_CurrentDate_2.Text) in OData__x0032_5M Or 
DateValue(lbl_CurrentDate_2.Text) in OData__x0031_00M
) Or

If(PylaRange_3.Value = true,
RangeComplex="Pyla Range Complex" And DateValue(StartDateTime) <= DateValue(lbl_CurrentDate_2.Text) And  DateValue(EndDateTime) >= DateValue(lbl_CurrentDate_2.Text) Or
DateValue(lbl_CurrentDate_2.Text) in IBSR Or 
DateValue(lbl_CurrentDate_2.Text) in ICQB Or
DateValue(lbl_CurrentDate_2.Text) in LFTTA Or 
DateValue(lbl_CurrentDate_2.Text) in UGL
) Or

If(AkiDry_3.Value = true,
TrainingArea="Akrotiri Dry Training Area" And DateValue(StartDateTime) <= DateValue(lbl_CurrentDate_2.Text) And  DateValue(EndDateTime) >= DateValue(lbl_CurrentDate_2.Text) Or
DateValue(lbl_CurrentDate_2.Text) in OData__x0057_1  Or 
DateValue(lbl_CurrentDate_2.Text) in W1_x0028_DriverTraining_x0029_  Or
DateValue(lbl_CurrentDate_2.Text) in W1A  Or 
DateValue(lbl_CurrentDate_2.Text) in W1A_x0028_UrbanOperationsTrainin  Or
DateValue(lbl_CurrentDate_2.Text) in W1AFOBPinetrack  Or 
DateValue(lbl_CurrentDate_2.Text) in W1AFOBPinetrackAccomodation  Or
DateValue(lbl_CurrentDate_2.Text) in W1B  Or 
DateValue(lbl_CurrentDate_2.Text) in W1C  Or
DateValue(lbl_CurrentDate_2.Text) in W1D  Or 
DateValue(lbl_CurrentDate_2.Text) in W1E  Or
DateValue(lbl_CurrentDate_2.Text) in OData__x0057_2
) Or
If(EpiDry_3.Value = true,
TrainingArea="Episkopi Dry Training Area" And DateValue(StartDateTime) <= DateValue(lbl_CurrentDate_2.Text) And  DateValue(EndDateTime) >= DateValue(lbl_CurrentDate_2.Text) Or
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_1 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_2 Or 
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_3 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_5 Or 
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_6 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_8 Or 
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_9 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_10 Or 
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_11 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_12 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_13 Or 
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_14 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x0057_3 Or 
DateValue(lbl_CurrentDate_2.Text) in OData__x0057_1 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x0057_5 
) Or
If(DhekDry_3.Value = true,
TrainingArea="Dhekelia Dry Training Area" And DateValue(StartDateTime) <= DateValue(lbl_CurrentDate_2.Text) And  DateValue(EndDateTime) >= DateValue(lbl_CurrentDate_2.Text) Or
DateValue(lbl_CurrentDate_2.Text) in W6A Or
DateValue(lbl_CurrentDate_2.Text) in W6B Or 
DateValue(lbl_CurrentDate_2.Text) in W6C
),
"Pyla/Dhek",

If(DhekRange_3.Value = true,
RangeComplex="Dhekelia Range Complex" And DateValue(StartDateTime) <= DateValue(lbl_CurrentDate_2.Text) And  DateValue(EndDateTime) >= DateValue(lbl_CurrentDate_2.Text) Or
DateValue(lbl_CurrentDate_2.Text) in ARange Or 
DateValue(lbl_CurrentDate_2.Text) in BRange Or
DateValue(lbl_CurrentDate_2.Text) in OData__x0032_5M Or 
DateValue(lbl_CurrentDate_2.Text) in OData__x0031_00M
) Or
If(PylaRange_3.Value = true,
RangeComplex="Pyla Range Complex" And DateValue(StartDateTime) <= DateValue(lbl_CurrentDate_2.Text) And  DateValue(EndDateTime) >= DateValue(lbl_CurrentDate_2.Text) Or
DateValue(lbl_CurrentDate_2.Text) in IBSR Or 
DateValue(lbl_CurrentDate_2.Text) in ICQB Or
DateValue(lbl_CurrentDate_2.Text) in LFTTA Or 
DateValue(lbl_CurrentDate_2.Text) in UGL
), "FTA",

If(AkiDry_3.Value = true,
TrainingArea="Akrotiri Dry Training Area" And DateValue(StartDateTime) <= DateValue(lbl_CurrentDate_2.Text) And  DateValue(EndDateTime) >= DateValue(lbl_CurrentDate_2.Text) Or
DateValue(lbl_CurrentDate_2.Text) in OData__x0057_1  Or 
DateValue(lbl_CurrentDate_2.Text) in W1_x0028_DriverTraining_x0029_  Or
DateValue(lbl_CurrentDate_2.Text) in W1A  Or 
DateValue(lbl_CurrentDate_2.Text) in W1A_x0028_UrbanOperationsTrainin  Or
DateValue(lbl_CurrentDate_2.Text) in W1AFOBPinetrack  Or 
DateValue(lbl_CurrentDate_2.Text) in W1AFOBPinetrackAccomodation  Or
DateValue(lbl_CurrentDate_2.Text) in W1B  Or 
DateValue(lbl_CurrentDate_2.Text) in W1C  Or
DateValue(lbl_CurrentDate_2.Text) in W1D  Or 
DateValue(lbl_CurrentDate_2.Text) in W1E  Or
DateValue(lbl_CurrentDate_2.Text) in OData__x0057_2
) Or
If(EpiDry_3.Value = true,
TrainingArea="Episkopi Dry Training Area" And DateValue(StartDateTime) <= DateValue(lbl_CurrentDate_2.Text) And  DateValue(EndDateTime) >= DateValue(lbl_CurrentDate_2.Text) Or
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_1 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_2 Or 
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_3 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_5 Or 
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_6 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_8 Or 
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_9 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_10 Or 
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_11 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_12 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_13 Or 
DateValue(lbl_CurrentDate_2.Text) in OData__x004c_14 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x0057_3 Or 
DateValue(lbl_CurrentDate_2.Text) in OData__x0057_1 Or
DateValue(lbl_CurrentDate_2.Text) in OData__x0057_5 
) Or
If(DhekDry_3.Value = true,
TrainingArea="Dhekelia Dry Training Area" And DateValue(StartDateTime) <= DateValue(lbl_CurrentDate_2.Text) And  DateValue(EndDateTime) >= DateValue(lbl_CurrentDate_2.Text) Or
DateValue(lbl_CurrentDate_2.Text) in W6A Or
DateValue(lbl_CurrentDate_2.Text) in W6B Or 
DateValue(lbl_CurrentDate_2.Text) in W6C
),
"Aki",

If(AkiRange_3.Value = true,
RangeComplex="Akrotiri Range Complex" And DateValue(StartDateTime) <= DateValue(lbl_CurrentDate_2.Text) And  DateValue(EndDateTime) >= DateValue(lbl_CurrentDate_2.Text) Or
DateValue(lbl_CurrentDate_2.Text) in ETR Or 
DateValue(lbl_CurrentDate_2.Text) in GroupingZeroing Or
DateValue(lbl_CurrentDate_2.Text) in MMTR Or 
DateValue(lbl_CurrentDate_2.Text) in CQB
))
)
,"StartDateTime", SortOrder.Ascending)

Click to expand
Project Image
User Area

This section focuses on the user area, providing users with a platform to review their bookings for confirmation or in case of oversight. Users have the option to expand the gallery to delve into their bookings in greater detail, facilitating a comprehensive view of their scheduled bookings.

Click to expand
Project Image
Admin Dashboard Screen

Displayed in the image is the splash screen for the admin area, clearly identified at the top. One notable feature that I particularly appreciate and have integrated into many of my apps is the dashboard view. In this instance, the dashboard enables booking staff to efficiently monitor the status of bookings for the day, including whether they are booked or not, along with the scheduled times.


The blocks even change colour to green for ongoing bookings, enhancing visibility. While seemingly small, this feature proves to be highly effective. Another aspect worth noting in this admin area is the expandable and collapsible navigation menu. This feature allows for seamless navigation within the admin area without occupying unnecessary space.

Click to expand
Project Image
Dynamic Information

I delved into the implementation of expandable and collapsible sections. Each block, featuring titles and arrows, is designed to expand and collapse, offering various functionalities.


Primarily, these sections enable the adjustment of dynamic values for email notifications, similarly to the previous project. Additionally, they facilitate the management of door codes, the opening and closing of specific ranges on designated dates, as well as temporary closures or openings until further notice, among other functionalities.

Click to expand
Project Image
Admin Area Booking Information

Upon selecting a booking, the screen presented showcases essential information for the team's reference. Additionally, it provides access for booking staff to view any attached documents by interacting with the buttons located at the bottom of the page.


This also enabled the booking staff to be able to make any changes to the users booking or delete/archive if required.

J6 Tasking Tool

Click to expand
Project Image
Opening Page

Upon launching the application, users are greeted with the initial screen displayed above. This screen serves as the gateway for users to select the specific station to which they intend to submit their ticket.


With a selection of 10 different stations available, this choice determines the data source to which the ticket will be patched when submitted.


Additionally, it subtly adjusts the categorization of ticket types within each section, reflecting variations that may exist across different stations. Further details on these distinctions will be elaborated upon in the subsequent section.

Click to expand
Project Image
Main Menu

After selecting their station, users will encounter the screen depicted above. Here, users can specify the type of request they wish to submit.


At this stage, ticket types are segregated based on the section to which they will be directed upon submission for this specific station.


Additionally, the top left corner features the 'Your Requests' button, which functions similarly to the admin area shown in another image, but of course only displaying the user's information.





If(IsBlank(Dropdown1.SelectedText),Set(varShowError, true), 

If(Dropdown1.SelectedText.Value = "Akrotiri" Or Dropdown1.SelectedText.Value = "Salt Lake Site",

ClearCollect(iHubOptions, Table(
        {
            Title1: "Outlook and Role Requests",
            Info1: "I need to change my job role or join a group mailbox.",
            Button1: OutlookAndRoleRequests_1,
            Title2: "New User Account and Arrivals",
            Info2: "I need to create a new MODNet account or I've just arrived on station.",
            Button2: NewUserAccountAndArrivals_1
        },
        {
            Title1: "SharePoint and Permissions Changes",
            Info1: "I need permissions to access a site or LTD area or I need to create a document libary.",
            Button1: SharePointAndPermissionChanges_1,
            Title2: "MODNet Laptop Request",
            Info2: "I have a requirement to be issued with a MODNet Laptop or my MODNet Laptop is U/S.",
            Button2: MODNETLaptopRequest_1
        },
        {
            Title1: "Unit Clearance",
            Info1: "I am clearing from Unit.",
            Button1: UnitClearance_1,
            Title2: "Software Request",
            Info2: "I need access to a specific application such as Power BI.",
            Button2: SoftwareRequest_1
        },
        {
         Title1: "PowerApps and Flows",
         Info1: "Include as much information as possible within the email.",
         Button1: QuestionScreen_1,
        Title2: "Carriage Certificate",
        Info2: "I need to take my MODNet device overseas.",
        Button2: CarriageCertificate_1
        }
    )
);

ClearCollect(ProjOptions, Table(
        {
            Title1: "Request For Change",
            Info1: "I want new Hardware such as a monitor or have a specific requirement.",
            Button1: RequestForChange_1,
            Title2: "Work Phone and Tablet Request and Transfer",
            Info2: "I have a requirement to be issued a work phone/work tablet or transfer my current phone/tablet to my replacement.",
            Button2: MODNETiPhoneAndiPadRequestAndTransfer_1
        },
        {
            Title1: "Fault Report",
            Info1: "I have reported faulty equipment to the Service Centre and they have advised me to contact my iHub.",
            Button1: FaultReport_1,
            Title2: "Planned Outage Requests",
            Info2: "I need to report a Planned Outage!",
            Button2: Outages_1
        }
    )
),




ClearCollect(iHubOptions, Table(
        {
            Title1: "Outlook and Role Requests",
            Info1: "I need to change my job role or join a group mailbox.",
            Button1: OutlookAndRoleRequests_1,
            Title2: "New User Account and Arrivals",
            Info2: "I need to create a new MODNet account or I've just arrived on station.",
            Button2: NewUserAccountAndArrivals_1
        },
        {
            Title1: "SharePoint and Permissions Changes",
            Info1: "I need permissions to access a site or LTD area or I need to create a document libary.",
            Button1: SharePointAndPermissionChanges_1,
            Title2: "MODNet Laptop Request",
            Info2: "I have a requirement to be issued with a MODNet Laptop or my MODNet Laptop is U/S.",
            Button2: MODNETLaptopRequest_1
        },
        {
            Title1: "Unit Clearance",
            Info1: "I am clearing from Unit.",
            Button1: UnitClearance_1,
            Title2: "Software Request",
            Info2: "I need access to a specific application such as Power BI.",
            Button2: SoftwareRequest_1
        },
        {
            Title1: "Work Phone and Tablet Request and Transfer",
            Info1: "I have a requirement to be issued a work phone/work tablet or transfer my current phone/tablet to my replacement.",
            Button1: MODNETiPhoneAndiPadRequestAndTransfer_1,
            Title2: "Carriage Certificate",
            Info2: "I need to take my MODNet device overseas.",
            Button2: CarriageCertificate_1
        
        }
    )
);

ClearCollect(ProjOptions, Table(
        {
            Title1: "Request For Change",
            Info1: "I want new Hardware such as a monitor or have a specific requirement.",
            Button1: RequestForChange_1,
            Title2: "Fault Report",
            Info2: "I have reported faulty equipment to the Service Centre and they have advised me to contact my iHub.",
            Button2: FaultReport_1
        },
        {
            Title1: "Planned Outage Requests",
            Info1: "I need to report a Planned Outage!",
            Button1: Outages_1,
            Title2: ""
        }
    )
));

Set(varStartScreen, false) And Set(varShowError, false));


Click to expand
Project Image
FTA Booking Screen

This image showcases a request for change ticket, which is representative of similar other tickets with varying question types.


Once all fields are completed, the submit button becomes active. Upon submission, the ticket is routed to the designated station and specific section, eventually residing in the unassigned queue, a process elaborated on in a subsequent section.


Below, you can observe the code snippet embedded in the submit button, ensuring the correct routing of the ticket to its designated location.





If(Dropdown1.SelectedText.Value = "Akrotiri" Or Dropdown1.SelectedText.Value = "Salt Lake Site",


If(IsBlank(ComboBox1_16.Selected.Mail), UpdateContext({varEmailError1: true}),
If(Radio1_5.Selected.Value = Text("Yes") And IsBlank(ComboBox1_6.Selected.Mail), UpdateContext({varEmailError: !varEmailError}),
Patch(
    'C4I Tasking Tool - Open Tasks - PowerApps',
    Defaults('C4I Tasking Tool - Open Tasks - PowerApps'),
    {
        Title: ComboBox1_16.Selected.Mail,
        Rank: TextInput4_21.Text,
        Role: TextInput4_22.Text,
        DateOfSubmission: Today(),
        PUID: Left(Mid(First(Split(ComboBox1_16.Selected.Mail, "@")).Value, Len(First(Split(ComboBox1_16.Selected.Mail, ".")).Value)+2), Len(Mid(First(Split(ComboBox1_16.Selected.Mail, "@")).Value, Len(First(Split(ComboBox1_16.Selected.Mail, ".")).Value)+2)) -3) & Left(First(Split(ComboBox1_16.Selected.Mail, ".")).Value, 1) &Right(First(Split(ComboBox1_16.Selected.Mail, "@")).Value, 3),
        Telephone: TextInput4_23.Text,
        DateRequired: DatePicker1_5.SelectedDate,
        LineManager: ComboBox1_6.Selected.Mail,
        TaskingType: "Request For Change",
        RequestType: Dropdown2_3.SelectedText.Value,
        RequestUIN: TextInput4_61.Text,
        RequestUnit: TextInput4_62.Text,
        RequestAssetNo: TextInput4_67.Text,
        RequestHardware: TextInput4_81.Text,
        RequestJustification: TextInput4_63.Text,
        RequestCurrentBldg: TextInput4_64.Text,
        RequestCurrentRoom: TextInput4_65.Text,
        RequestCurrentTap: TextInput4_66.Text,
        RequestNewBldg: TextInput4_82.Text,
        RequestNewRoom: TextInput4_83.Text,
        RequestNewTap: TextInput4_84.Text,
        RequestNewHardware: TextInput4_85.Text,
        RequestDevice: Radio3.Selected.Value,
        RequestInformation: TextInput4_86.Text,
        RequestRequirement: TextInput4_87.Text,
        Status: {Value: "Unassigned"}
    }
);
Navigate(SuccessScreen_1,ScreenTransition.Cover))),


If(IsBlank(ComboBox1_16.Selected.Mail), UpdateContext({varEmailError1: true}),
If(Radio1_5.Selected.Value = Text("Yes") And IsBlank(ComboBox1_6.Selected.Mail), UpdateContext({varEmailError: !varEmailError}),
Patch(
    'J6 Tasking Tool - Open Tasks - PowerApps',
    Defaults('J6 Tasking Tool - Open Tasks - PowerApps'),
    {
        Title: ComboBox1_16.Selected.Mail,
        Rank: TextInput4_21.Text,
        Role: TextInput4_22.Text,
        DateOfSubmission: Today(),
        PUID: Left(Mid(First(Split(ComboBox1_16.Selected.Mail, "@")).Value, Len(First(Split(ComboBox1_16.Selected.Mail, ".")).Value)+2), Len(Mid(First(Split(ComboBox1_16.Selected.Mail, "@")).Value, Len(First(Split(ComboBox1_16.Selected.Mail, ".")).Value)+2)) -3) & Left(First(Split(ComboBox1_16.Selected.Mail, ".")).Value, 1) &Right(First(Split(ComboBox1_16.Selected.Mail, "@")).Value, 3),
        Telephone: TextInput4_23.Text,
        DateRequired: DatePicker1_5.SelectedDate,
        LineManager: ComboBox1_6.Selected.Mail,
        TaskingType: "Request For Change",
        RequestType: Dropdown2_3.SelectedText.Value,
        RequestUIN: TextInput4_61.Text,
        RequestUnit: TextInput4_62.Text,
        RequestAssetNo: TextInput4_67.Text,
        RequestHardware: TextInput4_81.Text,
        RequestJustification: TextInput4_63.Text,
        RequestCurrentBldg: TextInput4_64.Text,
        RequestCurrentRoom: TextInput4_65.Text,
        RequestCurrentTap: TextInput4_66.Text,
        RequestNewBldg: TextInput4_82.Text,
        RequestNewRoom: TextInput4_83.Text,
        RequestNewTap: TextInput4_84.Text,
        RequestNewHardware: TextInput4_85.Text,
        RequestDevice: Radio3.Selected.Value,
        RequestInformation: TextInput4_86.Text,
        RequestRequirement: TextInput4_87.Text,
        Status: {Value: "Unassigned"}
    }
);
Navigate(SuccessScreen_1,ScreenTransition.Cover))));


Click to expand
Project Image
Admin Main Screen

Upon launching the admin side of the tool, users are greeted with the opening screen in a separate PowerApp to the user tool. At the centre, a small contact card welcomes the staff. To the right of the contact card, a button directs users to Episkopi's tasking tool admin area.


On the left, the screen displays the current number of tickets in the admin area awaiting action or currently being processed for this specific station. The breakdown of tickets in each section is also visible. It's important to note that these numbers may not add up to the total due to tickets being assignable to individuals as well as sections, with further details explained on another card.


Below this information, four large buttons are presented. The first button leads to a page where staff are able to view and action all tickets submitted by users. The button to the right of this is designated for internal tasks, allowing for effective tracking and follow-up by management.


Adjacent to this is the outage tracker, enabling users to submit planned outages for review and action. Lastly, there is the cost tracker button, which consolidates information inputted by admin staff on each ticket regarding ordered items, presenting it in a readable format for costing reports and analysis.

Click to expand
Project Image
Ticket Viewing Screen

This page serves as a central hub for staff to manage user tickets assigned to themselves or their team. The screen layout includes a navigation bar on the left for easy movement within the ticket tracker section. At the top, a filter enables users to display specific ticket types, streamlining the search process. The search function, available only on the 'Open Tickets' page, allows staff to search by names, IDs and more.


Each ticket can be selected and expanded to reveal all necessary details for completing the assigned tasks. Information such as the assignee and current status is prominently displayed. Adjacent to this information are various icons that facilitate specific actions on the ticket. The icons include options for adding comments and financial details, setting reminders, reassigning tickets, changing status', and deleting/archiving tickets. Any modifications trigger automated email notifications to keep users informed.


On the right side of each ticket, a blue status dot indicates the ticket's status and whether there are any comments. The dot changes colour dynamically, providing a quick visual cue for the team to assess the ticket's status without opening it for further details.

Click to expand
Project Image
Comments Popup

This section showcases the comment feature discussed in a previous card, enabling staff to add comments to specific tickets. In the example above, the screen displays the date, time, and initials of the staff member who added the comment, promoting accountability. While comments can be deleted, a record of the comment is still included in the automated email sent to the user.


The system utilises a relational database to support multiple comments on a single ticket, proving effective even with extensive data sets.


Within the pop-up window, there is a financial information section located at the bottom. This section is crucial when the team needs to make financial decisions, such as purchasing equipment or software. Staff are required to input all relevant information to assist the costing manager in tracking these details for budgeting purposes.

Click to expand
Project Image
Cost Tracker

Within this screen, you will find a comprehensive overview of costings. It displays a detailed list of tickets, each associated with specific costs and essential information crucial for cost management. The screen also features a prominent display of total costs at the top for quick reference. Notably, the filtering functionality on this page is highly effective, allowing users to efficiently locate specific tickets by applying relevant filters.




ClearCollect(ColTicketCostOpen,AddColumns(ShowColumns(Filter('C4I Tasking Tool - Open Tasks - PowerApps', !IsBlank(Cost)), ID, 'Item Type & Qty','Order Date', 'Received Date', Cost, OrderType, RefNo), Site, "Aki"));
Collect(ColTicketCostOpen,AddColumns(ShowColumns(Filter('C4I Tasking Tool - Closed Tasks - PowerApps', !IsBlank(Cost)), IDRef, 'Item Type & Qty','Order Date', 'Received Date', Cost, OrderType, RefNo), Site, "Aki"));
Collect(ColTicketCostOpen,AddColumns(ShowColumns(Filter('J6 Tasking Tool - Open Tasks - PowerApps', !IsBlank(Cost)), ID, 'Item Type & Qty','Order Date', 'Received Date', Cost, OrderType, RefNo), Site, "Epi"));
Collect(ColTicketCostOpen,AddColumns(ShowColumns(Filter('J6 Tasking Tool - Closed Tasks - PowerApps', !IsBlank(Cost)), IDRef, 'Item Type & Qty','Order Date', 'Received Date', Cost, OrderType, RefNo), Site, "Epi"));

If(SwitchFilter="Order Date",

If(IsBlank(Drp_Cost_Filter_Site.SelectedText.Value), 
If(IsBlank(Drp_Cost_Filter_OrderType.SelectedText.Value),
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(ColTicketCostOpen, SortOrder.Ascending),
Filter(ColTicketCostOpen, OrderDate >= Dpr_Cost_Filter_FromDate.SelectedDate, OrderDate <=Dpr_Cost_Filter_ToDate.SelectedDate)),
If(Drp_Cost_Filter_OrderType.SelectedText.Value="CP&F", 
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, OrderType="CP&F"), SortOrder.Ascending),
Filter(ColTicketCostOpen, OrderDate >= Dpr_Cost_Filter_FromDate.SelectedDate, OrderDate <=Dpr_Cost_Filter_ToDate.SelectedDate And OrderType="CP&F")),
If(Drp_Cost_Filter_OrderType.SelectedText.Value="DDC", 
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, OrderType="DDC"), SortOrder.Ascending),
Filter(ColTicketCostOpen, OrderDate >= Dpr_Cost_Filter_FromDate.SelectedDate, OrderDate <=Dpr_Cost_Filter_ToDate.SelectedDate And OrderType="DDC"))))),

If(Drp_Cost_Filter_Site.SelectedText.Value="Akrotiri",
If(IsBlank(Drp_Cost_Filter_OrderType.SelectedText.Value),
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, Site="Aki"),SortOrder.Ascending),
Filter(ColTicketCostOpen, OrderDate >= Dpr_Cost_Filter_FromDate.SelectedDate, OrderDate <=Dpr_Cost_Filter_ToDate.SelectedDate And Site="Aki")),
If(Drp_Cost_Filter_OrderType.SelectedText.Value="CP&F", 
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, Site="Aki" And OrderType="CP&F"),SortOrder.Ascending),
Filter(ColTicketCostOpen, OrderDate >= Dpr_Cost_Filter_FromDate.SelectedDate, OrderDate <=Dpr_Cost_Filter_ToDate.SelectedDate And OrderType="CP&F" And Site="Aki")),
If(Drp_Cost_Filter_OrderType.SelectedText.Value="DDC", 
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, Site="Aki" And OrderType="DDC"),SortOrder.Ascending),
Filter(ColTicketCostOpen, OrderDate >= Dpr_Cost_Filter_FromDate.SelectedDate, OrderDate <=Dpr_Cost_Filter_ToDate.SelectedDate And OrderType="DDC" And Site="Aki"))))),

If(Drp_Cost_Filter_Site.SelectedText.Value="Episkopi",
If(IsBlank(Drp_Cost_Filter_OrderType.SelectedText.Value),
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, Site="Epi"), SortOrder.Ascending),
Filter(ColTicketCostOpen, OrderDate >= Dpr_Cost_Filter_FromDate.SelectedDate, OrderDate <=Dpr_Cost_Filter_ToDate.SelectedDate And Site="Epi")),
If(Drp_Cost_Filter_OrderType.SelectedText.Value="CP&F", 
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, Site="Epi" And OrderType="CP&F"), SortOrder.Ascending),
Filter(ColTicketCostOpen, OrderDate >= Dpr_Cost_Filter_FromDate.SelectedDate, OrderDate <=Dpr_Cost_Filter_ToDate.SelectedDate And OrderType="CP&F" And Site="Epi")),
If(Drp_Cost_Filter_OrderType.SelectedText.Value="DDC", 
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, Site="Epi" And OrderType="DDC"), SortOrder.Ascending),
Filter(ColTicketCostOpen, OrderDate >= Dpr_Cost_Filter_FromDate.SelectedDate, OrderDate <=Dpr_Cost_Filter_ToDate.SelectedDate And OrderType="DDC" And Site="Epi")))))))),


If(IsBlank(Drp_Cost_Filter_Site.SelectedText.Value), 
If(IsBlank(Drp_Cost_Filter_OrderType.SelectedText.Value),
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, !IsBlank(ReceivedDate)), SortOrder.Ascending),
Filter(ColTicketCostOpen, ReceivedDate >= Dpr_Cost_Filter_FromDate.SelectedDate, ReceivedDate <=Dpr_Cost_Filter_ToDate.SelectedDate)),
If(Drp_Cost_Filter_OrderType.SelectedText.Value="CP&F", 
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, !IsBlank(ReceivedDate) And OrderType="CP&F"), SortOrder.Ascending),
Filter(ColTicketCostOpen, ReceivedDate >= Dpr_Cost_Filter_FromDate.SelectedDate, ReceivedDate <=Dpr_Cost_Filter_ToDate.SelectedDate And OrderType="CP&F")),
If(Drp_Cost_Filter_OrderType.SelectedText.Value="DDC", 
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, !IsBlank(ReceivedDate) And OrderType="DCC"), SortOrder.Ascending),
Filter(ColTicketCostOpen, ReceivedDate >= Dpr_Cost_Filter_FromDate.SelectedDate, ReceivedDate <=Dpr_Cost_Filter_ToDate.SelectedDate And OrderType="DDC"))))),

If(Drp_Cost_Filter_Site.SelectedText.Value="Akrotiri",
If(IsBlank(Drp_Cost_Filter_OrderType.SelectedText.Value),
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, !IsBlank(ReceivedDate) And Site="Aki"), SortOrder.Ascending),
Filter(ColTicketCostOpen, ReceivedDate >= Dpr_Cost_Filter_FromDate.SelectedDate, ReceivedDate <=Dpr_Cost_Filter_ToDate.SelectedDate And Site="Aki")),
If(Drp_Cost_Filter_OrderType.SelectedText.Value="CP&F", 
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, !IsBlank(ReceivedDate) And Site="Aki" And OrderType="CP&F"), SortOrder.Ascending),
Filter(ColTicketCostOpen, ReceivedDate >= Dpr_Cost_Filter_FromDate.SelectedDate, ReceivedDate <=Dpr_Cost_Filter_ToDate.SelectedDate And OrderType="CP&F" And Site="Aki")),
If(Drp_Cost_Filter_OrderType.SelectedText.Value="DDC", 
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, !IsBlank(ReceivedDate) And Site="Aki" And OrderType="DDC"), SortOrder.Ascending),
Filter(ColTicketCostOpen, ReceivedDate >= Dpr_Cost_Filter_FromDate.SelectedDate, ReceivedDate <=Dpr_Cost_Filter_ToDate.SelectedDate And OrderType="DDC" And Site="Aki"))))),

If(Drp_Cost_Filter_Site.SelectedText.Value="Episkopi",
If(IsBlank(Drp_Cost_Filter_OrderType.SelectedText.Value),
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, !IsBlank(ReceivedDate) And Site="Epi"), SortOrder.Ascending),
Filter(ColTicketCostOpen, ReceivedDate >= Dpr_Cost_Filter_FromDate.SelectedDate, ReceivedDate <=Dpr_Cost_Filter_ToDate.SelectedDate And Site="Epi")),
If(Drp_Cost_Filter_OrderType.SelectedText.Value="CP&F", 
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, !IsBlank(ReceivedDate) And Site="Epi" And OrderType="CP&F"), SortOrder.Ascending),
Filter(ColTicketCostOpen, ReceivedDate >= Dpr_Cost_Filter_FromDate.SelectedDate, ReceivedDate <=Dpr_Cost_Filter_ToDate.SelectedDate And OrderType="CP&F" And Site="Epi")),
If(Drp_Cost_Filter_OrderType.SelectedText.Value="DDC", 
If(IsBlank(Dpr_Cost_Filter_FromDate.SelectedDate) And IsBlank(Dpr_Cost_Filter_ToDate.SelectedDate),
Sort(Filter(ColTicketCostOpen, !IsBlank(ReceivedDate) And Site="Epi" And OrderType="DDC"), SortOrder.Ascending),
Filter(ColTicketCostOpen, ReceivedDate >= Dpr_Cost_Filter_FromDate.SelectedDate, ReceivedDate <=Dpr_Cost_Filter_ToDate.SelectedDate And OrderType="DDC" And Site="Epi")))))))))

Click to expand
Project Image
Ticket Viewing Screen

On the same page, individuals from other sections will encounter a distinct view. They will observe varied tickets and encounter a unique filter positioned at the top of the page. This filter enables users from different sections to refine their displayed tickets based on diverse ticket types.





If(varSections = "iHub",
If(
varCurrentTab6= "All",
SortByColumns(Filter(ColOpenTasks, 
AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="In Progress" Or 
AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="On Hold" Or 
AssignedSection = varSections And Status.Value="In Progress" Or 
AssignedSection = varSections And Status.Value="On Hold"), "TaskPriority"),
If(
varCurrentTab6= "Outlook & Role Requests",
SortByColumns(Filter(ColOpenTasks, 
TaskingType="Outlook and Role Requests" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="In Progress" Or 
TaskingType="Outlook and Role Requests" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="On Hold" Or 
TaskingType="Outlook and Role Requests" And AssignedSection = varSections And Status.Value="In Progress" Or 
TaskingType="Outlook and Role Requests" And AssignedSection = varSections And Status.Value="On Hold"), "TaskPriority"),
If(
varCurrentTab6= "SharePoint & Permission Changes",
SortByColumns(Filter(ColOpenTasks, 
TaskingType="Sharepoint And Permission Changes" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="In Progress" Or 
TaskingType="Sharepoint And Permission Changes" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="On Hold" Or 
TaskingType="Sharepoint And Permission Changes" And AssignedSection = varSections And Status.Value="In Progress" Or 
TaskingType="Sharepoint And Permission Changes" And AssignedSection = varSections And Status.Value="On Hold"), "TaskPriority"),
If(
varCurrentTab6= "Software Request",
SortByColumns(Filter(ColOpenTasks, 
TaskingType="Software Request" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="In Progress" Or 
TaskingType="Software Request" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="On Hold" Or 
TaskingType="Software Request" And AssignedSection = varSections And Status.Value="In Progress" Or 
TaskingType="Software Request" And AssignedSection = varSections And Status.Value="On Hold"), "TaskPriority"),
If(
varCurrentTab6= "Laptop Request",
SortByColumns(Filter(ColOpenTasks, 
TaskingType="MODNet Laptop Request" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="In Progress" Or 
TaskingType="MODNet Laptop Request" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="On Hold" Or 
TaskingType="MODNet Laptop Request" And AssignedSection = varSections And Status.Value="In Progress" Or 
TaskingType="MODNet Laptop Request" And AssignedSection = varSections And Status.Value="On Hold"), "TaskPriority"),
If(
varCurrentTab6= "New User Account & Arrivals",
SortByColumns(Filter(ColOpenTasks, 
TaskingType="New User Account And Arrivals" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="In Progress" Or 
TaskingType="New User Account And Arrivals" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="On Hold" Or 
TaskingType="New User Account And Arrivals" And AssignedSection = varSections And Status.Value="In Progress" Or 
TaskingType="New User Account And Arrivals" And AssignedSection = varSections And Status.Value="On Hold"), "TaskPriority"),
If(
varCurrentTab6= "Unit Clearance",
SortByColumns(Filter(ColOpenTasks, 
TaskingType="Unit Clearance" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="In Progress" Or 
TaskingType="Unit Clearance" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="On Hold" Or 
TaskingType="Unit Clearance" And AssignedSection = varSections And Status.Value="In Progress" Or 
TaskingType="Unit Clearance" And AssignedSection = varSections And Status.Value="On Hold"), "TaskPriority")))))))),
If(varSections = "Projects",
If(
varCurrentTab6= "All",
SortByColumns(Filter(ColOpenTasks, 
AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="In Progress" Or 
AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="On Hold" Or 
AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="Awaiting Business Case" Or 
AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="Awaiting Financial Approval" Or 
AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="Bulk Orders" Or 
AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="Ordered" Or 
AssignedSection = varSections And Status.Value="In Progress" Or 
AssignedSection = varSections And Status.Value="On Hold" Or 
AssignedSection = varSections And Status.Value="Awaiting Business Case" Or 
AssignedSection = varSections And Status.Value="Awaiting Financial Approval" Or 
AssignedSection = varSections And Status.Value="Bulk Orders" Or 
AssignedSection = varSections And Status.Value="Ordered"), "ID"),
If(
varCurrentTab6= "Request For Change",
SortByColumns(Filter(ColOpenTasks, 
TaskingType="Request For Change" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="In Progress" Or 
TaskingType="Request For Change" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="On Hold" Or 
TaskingType="Request For Change" And AssignedSection = varSections And Status.Value="In Progress" Or 
TaskingType="Request For Change" And AssignedSection = varSections And Status.Value="On Hold"), "ID"),

If(
varCurrentTab6= "iPhone & iPad Request and Transfer",
SortByColumns(Filter(ColOpenTasks, 
TaskingType="MODNet iPhone and iPad Requests and Transfers" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="In Progress" Or 
TaskingType="MODNet iPhone and iPad Requests and Transfers" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="On Hold" Or 
TaskingType="MODNet iPhone and iPad Requests and Transfers" And AssignedSection = varSections And Status.Value="In Progress" Or 
TaskingType="MODNet iPhone and iPad Requests and Transfers" And AssignedSection = varSections And Status.Value="On Hold"), "ID"),
If(
varCurrentTab6= "Fault Report",
SortByColumns(Filter(ColOpenTasks, 
TaskingType="Fault Report" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="In Progress" Or 
TaskingType="Fault Report" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="On Hold" Or 
TaskingType="Fault Report" And AssignedSection = varSections And Status.Value="In Progress" Or 
TaskingType="Fault Report" And AssignedSection = varSections And Status.Value="On Hold"), "ID"),
If(
varCurrentTab6= "Comms Channel",
SortByColumns(Filter(ColOpenTasks, 
TaskingType="Comms Channel" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="In Progress" Or 
TaskingType="Comms Channel" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="On Hold" Or 
TaskingType="Comms Channel" And AssignedSection = varSections And Status.Value="In Progress" Or 
TaskingType="Comms Channel" And AssignedSection = varSections And Status.Value="On Hold"), "ID"),
If(
varCurrentTab6= "Awaiting Business Case",
SortByColumns(Filter(ColOpenTasks, 
TaskingType="Request For Change" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="Awaiting Business Case" Or 
TaskingType="Request For Change" And AssignedSection = varSections And Status.Value="Awaiting Business Case"), "ID"),
If(
varCurrentTab6= "Awaiting Financial Approval",
SortByColumns(Filter(ColOpenTasks, 
TaskingType="Request For Change" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="Awaiting Financial Approval" Or 
TaskingType="Request For Change" And AssignedSection = varSections And Status.Value="Awaiting Financial Approval"), "ID"),
If(
varCurrentTab6= "Bulk Orders",
SortByColumns(Filter(ColOpenTasks, 
TaskingType="Request For Change" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="Bulk Orders" Or 
TaskingType="Request For Change" And AssignedSection = varSections And Status.Value="Bulk Orders"), "ID"),
If(
varCurrentTab6= "Ordered",
SortByColumns(Filter(ColOpenTasks, 
TaskingType="Request For Change" And AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="Ordered" Or 
TaskingType="Request For Change" And AssignedSection = varSections And Status.Value="Ordered"), "ID")
))))))))),
If(varSections="Other", 
SortByColumns(Filter(ColOpenTasks, 
AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="In Progress" Or 
AssignedTo=Office365Users.UserProfile(User().Email).DisplayName And Status.Value="On Hold"
), "TaskPriority"))))


Click to expand
Project Image
Statistics Page

Displayed on the statistics screen is an overview accessible to all staff members. It showcases the number of tasks submitted within the last month, last two months, or last three months. Users have the option to apply additional filters to view data specific to individual sections or personnel. The screen also presents a graph illustrating the quantity and categories of closed tickets for a comprehensive insight.





CountRows(

If(varCurrentTab1 = "All" And varCurrentTab3 = "Last Month", Filter('C4I Tasking Tool - Closed Tasks - PowerApps', DateOfSubmission >= DateAdd(Today(), -1, TimeUnit.Months)), 
If(varCurrentTab1 = "All" And varCurrentTab3 = "Last 2 Months", Filter('C4I Tasking Tool - Closed Tasks - PowerApps', DateOfSubmission >= DateAdd(Today(), -2, TimeUnit.Months)), 
If(varCurrentTab1 = "All" And varCurrentTab3 = "Last 3 Months", Filter('C4I Tasking Tool - Closed Tasks - PowerApps', DateOfSubmission >= DateAdd(Today(), -3, TimeUnit.Months)),

If(varCurrentTab1= "iHub" And varCurrentTab3 = "Last Month", Filter('C4I Tasking Tool - Closed Tasks - PowerApps', TaskingType = "Sharepoint And Permission Changes" And DateOfSubmission >= DateAdd(Today(), -1, TimeUnit.Months) Or TaskingType = "MODNet Laptop Request" And DateOfSubmission >= DateAdd(Today(), -1, TimeUnit.Months) Or TaskingType = "Outlook and Role Requests" And DateOfSubmission >= DateAdd(Today(), -1, TimeUnit.Months) Or TaskingType = "Software Request" And DateOfSubmission >= DateAdd(Today(), -1, TimeUnit.Months) Or TaskingType = "New User Account And Arrivals" And DateOfSubmission >= DateAdd(Today(), -1, TimeUnit.Months) Or TaskingType = "Unit Clearance" And DateOfSubmission >= DateAdd(Today(), -1, TimeUnit.Months)), 

If(varCurrentTab1= "iHub" And varCurrentTab3 = "Last 2 Months", Filter('C4I Tasking Tool - Closed Tasks - PowerApps', TaskingType = "Sharepoint And Permission Changes" And DateOfSubmission >= DateAdd(Today(), -2, TimeUnit.Months) Or TaskingType = "MODNet Laptop Request" And DateOfSubmission >= DateAdd(Today(), -2, TimeUnit.Months) Or TaskingType = "Outlook and Role Requests" And DateOfSubmission >= DateAdd(Today(), -2, TimeUnit.Months) Or TaskingType = "Software Request" And DateOfSubmission >= DateAdd(Today(), -2, TimeUnit.Months) Or TaskingType = "New User Account And Arrivals" And DateOfSubmission >= DateAdd(Today(), -2, TimeUnit.Months) Or TaskingType = "Unit Clearance" And DateOfSubmission >= DateAdd(Today(), -2, TimeUnit.Months)), 

If(varCurrentTab1= "iHub" And varCurrentTab3 = "Last 3 Months", Filter('C4I Tasking Tool - Closed Tasks - PowerApps', TaskingType = "Sharepoint And Permission Changes" And DateOfSubmission >= DateAdd(Today(), -3, TimeUnit.Months) Or TaskingType = "MODNet Laptop Request" And DateOfSubmission >= DateAdd(Today(), -3, TimeUnit.Months) Or TaskingType = "Outlook and Role Requests" And DateOfSubmission >= DateAdd(Today(), -3, TimeUnit.Months) Or TaskingType = "Software Request" And DateOfSubmission >= DateAdd(Today(), -3, TimeUnit.Months) Or TaskingType = "New User Account And Arrivals" And DateOfSubmission >= DateAdd(Today(), -3, TimeUnit.Months) Or TaskingType = "Unit Clearance" And DateOfSubmission >= DateAdd(Today(), -3, TimeUnit.Months)), 

If(varCurrentTab1= "Projects" And varCurrentTab3 = "Last Month", Filter('C4I Tasking Tool - Closed Tasks - PowerApps', TaskingType = "Request For Change" And DateOfSubmission >= DateAdd(Today(), -1, TimeUnit.Months) Or TaskingType = "MODNet iPhone and iPad Requests and Transfers" And DateOfSubmission >= DateAdd(Today(), -1, TimeUnit.Months) Or TaskingType = "Fault Report" And DateOfSubmission >= DateAdd(Today(), -1, TimeUnit.Months)),

If(varCurrentTab1= "Projects" And varCurrentTab3 = "Last 2 Months", Filter('C4I Tasking Tool - Closed Tasks - PowerApps', TaskingType = "Request For Change" And DateOfSubmission >= DateAdd(Today(), -2, TimeUnit.Months) Or TaskingType = "MODNet iPhone and iPad Requests and Transfers" And DateOfSubmission >= DateAdd(Today(), -2, TimeUnit.Months) Or TaskingType = "Fault Report" And DateOfSubmission >= DateAdd(Today(), -2, TimeUnit.Months)),

If(varCurrentTab1= "Projects" And varCurrentTab3 = "Last 3 Months", Filter('C4I Tasking Tool - Closed Tasks - PowerApps', TaskingType = "Request For Change" And DateOfSubmission >= DateAdd(Today(), -3, TimeUnit.Months) Or TaskingType = "MODNet iPhone and iPad Requests and Transfers" And DateOfSubmission >= DateAdd(Today(), -3, TimeUnit.Months) Or TaskingType = "Fault Report" And DateOfSubmission >= DateAdd(Today(), -3, TimeUnit.Months))))))))))))


SortByColumns(
  AddColumns(
     If(varCurrentTab1 = "All",Filter('C4i Tasking Tool - Personnel - PowerApps', Section.Value = "iHub" Or Section.Value = "Projects"), 
If(varCurrentTab1 = "iHub", Filter('C4i Tasking Tool - Personnel - PowerApps', Section.Value = "iHub"), 
Filter('C4i Tasking Tool - Personnel - PowerApps', Section.Value = "Projects"))) As X,
     ticketsCount,
     CountIf(ColTickets,X.Personnel.DisplayName in AssignedTo) + 
CountIf(ColTickets,If(CountRows(Filter('C4i Tasking Tool - Personnel - PowerApps',X.Personnel.DisplayName = Personnel.DisplayName And Section.Value = "iHub"))>0, "iHub","Projects") in AssignedSection)
  ),
"ticketsCount",
SortOrder.Descending
)

Click to expand
Project Image
Unassigned Ticket Screen

The unassigned screen serves as the initial destination for newly submitted tickets. Here, staff members can allocate tickets to the appropriate section or individual. They also have the capability to transfer the ticket to another station's tool or delete it. Notably, selecting the deletion option triggers a prompt for staff to provide a reason for the deletion. This reason is then communicated to the user via an automated email notification.

Carriage Certificate

Click to expand
Project Image
Question Screen

This page is where users can request carriage certificates within the Tasking Tool PowerApp. Although these projects were completed at different times, we decided to consolidate them for a more streamlined approach. Users will input all necessary information here and receive a confirmation message upon submission. Further instructions for subsequent actions will be detailed on subsequent cards.





If(Radio5.Selected.Value="Yes" And Dropdown3.SelectedText.Value <> "Other",

'C4iTaskingTool-CarriageCertificate'.Run(

ComboBox1_19.Selected.GivenName & " " & ComboBox1_19.Selected.Surname, //Name
TextInput4_33.Text, //Rank
TextInput4_34.Text, //Role
TextInput4_35.Text, //ServiceNumber
TextInput4_224.Text, //PassportNumber
Dropdown1.SelectedText.Value, //Station
Dropdown3.SelectedText.Value, //Make&Model
ComboBox1_19.Selected.Mail, //Email
TextInput4_212.Text, //AssetNumber
"N/A", //Location-
"N/A", //OtherDevice
Text(DatePicker3.SelectedDate,"yyyy-mm-dd"),
Text(DatePicker3_1.SelectedDate,"yyyy-mm-dd")
),

If(Radio5.Selected.Value="No" And Dropdown3.SelectedText.Value <> "Other",

'C4iTaskingTool-CarriageCertificate'.Run(

ComboBox1_19.Selected.GivenName & " " & ComboBox1_19.Selected.Surname, //Name
TextInput4_33.Text, //Rank
TextInput4_34.Text, //Role
TextInput4_35.Text, //ServiceNumber
TextInput4_224.Text, //PassportNumber
Dropdown1.SelectedText.Value, //Station
Dropdown3.SelectedText.Value, //Make&Model
ComboBox1_19.Selected.Mail, //Email
TextInput4_212.Text, //AssetNumber
TextInput4_229.Text, //Location-
"N/A", //OtherDevice
Text(DatePicker3.SelectedDate,"yyyy-mm-dd"),
Text(DatePicker3_1.SelectedDate,"yyyy-mm-dd")
),

If(Radio5.Selected.Value="Yes" And Dropdown3.SelectedText.Value = "Other",

'C4iTaskingTool-CarriageCertificate'.Run(

ComboBox1_19.Selected.GivenName & " " & ComboBox1_19.Selected.Surname, //Name
TextInput4_33.Text, //Rank
TextInput4_34.Text, //Role
TextInput4_35.Text, //ServiceNumber
TextInput4_224.Text, //PassportNumber
Dropdown1.SelectedText.Value, //Station
Dropdown3.SelectedText.Value, //Make&Model
ComboBox1_19.Selected.Mail, //Email
TextInput4_212.Text, //AssetNumber
"N/A", //Location-
TextInput4_215.Text, //OtherDevice
Text(DatePicker3.SelectedDate,"yyyy-mm-dd"),
Text(DatePicker3_1.SelectedDate,"yyyy-mm-dd")
),

If(Radio5.Selected.Value="No" And Dropdown3.SelectedText.Value = "Other",

'C4iTaskingTool-CarriageCertificate'.Run(

ComboBox1_19.Selected.GivenName & " " & ComboBox1_19.Selected.Surname, //Name
TextInput4_33.Text, //Rank
TextInput4_34.Text, //Role
TextInput4_35.Text, //ServiceNumber
TextInput4_224.Text, //PassportNumber
Dropdown1.SelectedText.Value, //Station
Dropdown3.SelectedText.Value, //Make&Model
ComboBox1_19.Selected.Mail, //Email
TextInput4_212.Text, //AssetNumber
TextInput4_229.Text, //Location-
TextInput4_215.Text, //OtherDevice
Text(DatePicker3.SelectedDate,"yyyy-mm-dd"),
Text(DatePicker3_1.SelectedDate,"yyyy-mm-dd")
)
))));

Navigate(SuccessScreen_1,ScreenTransition.Cover)



Click to expand
Project Image
First Flow

The process depicted illustrates the transfer of data from PowerApps to a SharePoint list. While this flow may appear more extensive than typical, it is designed to accommodate variable blocks that rearrange information to ensure it is correctly formatted for document printing.

Click to expand
Project Image
Second Flow

After the previous flow, this flow immediately follows. Initially, it verifies whether the request pertains solely to the UK or involves another country/s. Once this determination is made, the process continues accordingly.


Firstly, a confirmation email is dispatched to the user, acknowledging the successful saving of the request, which will be reviewed by the staff in due course. Subsequently, depending on whether the assets are destined for a country other than the UK, the request may be redirected for further scrutiny and approval. Following this, the process remains consistent: it progresses to J6 for final approval.


This step is facilitated through an automated email containing approval buttons, directed to a group mailbox. Upon approval, data is extracted from the SharePoint list and compiled into a Word document bearing the digital signatures of the staff. The document is then automatically converted into a PDF format and dispatched to the user. This streamlined system not only significantly reduced manual labour but also enabled the office to execute this task with minimal paper usage.

Outage Tracker

Click to expand
Project Image
Questions Screen

The image above showcases a layout reminiscent of the Tasking Tool Project, as it pertains to the same tool. However, I have chosen to present it as a separate project due to its completion at a different time, despite being integrated into the same tool for convenience and centralisation.


Notably, the system includes a feature where outages must be submitted 30 working days before their start date. Should a user select a date outside this timeframe, a warning message will promptly appear to alert them of the requirement. Other than this it functions the same.





Set(SetID, 'C4IOutageTracker-Patch'.Run(
ComboBox1_21.Selected.Mail, //Email
TextInput4_216.Text, //Rank
TextInput4_217.Text, //Role
TextInput4_218.Text, //Ext
TextInput4_219.Text, //Service No
TextInput4_220.Text, //Organisaiton
Text(DatePicker2.SelectedDate, "yyyy-mm-dd"), //StartDate
Text(DatePicker2_1.SelectedDate, "yyyy-mm-dd"), //EndDate
sTime.SelectedText.Value, //StartTime
sTime_1.SelectedText.Value, //EndTime
TextInput4_222.Text, //ReasonForOutage
TextInput4_221.Text, //AddInfo
Dropdown1_2.SelectedText.Value, //TypeOfOutage
TextInput4_227.Text, //EffectOfOutage
Dropdown1_1.SelectedText.Value, //SiteAffected
Radio2_8.Selected.Value, //StandByPower
TextInput4_223.Text //PrimaryLocation
).ID);


ForAll(ColCustodian, If(!IsBlank(Title), Patch('C4i Tasking Tool - Outage Bldgs - PowerApps', Defaults('C4i Tasking Tool - Outage Bldgs - PowerApps'),
{RefID: SetID, Title: Title})));

Navigate(SuccessScreen_1,ScreenTransition.Cover);



Click to expand
Project Image
Outage Viewing Screen

Displayed above is the admin side of the Outage Tracker, which is basically the same as the Tasking Tool layout. However, a notable difference lies in the advanced filtering system.


Selecting an item opens a new page for detailed viewing, as illustrated in the subsequent card.

Click to expand
Project Image
Outage Info Screen 1

Upon reflection, I find myself dissatisfied with the visual presentation of this particular page within the app, a sentiment that extends to the entire application. Despite this visual concern, the functionality meets the necessary requirements. Over time, my proficiency in crafting aesthetically pleasing apps has improved.


The key ticket information is strategically positioned on the left and top sections of the page. The central box serves as the space where GC and BT can provide their impact statements. The layout of the boxes is designed to facilitate easy input of pertinent information by staff with minimal effort.


Just above these input fields, a tab system is visible, which dynamically reveals and highlights the subsequent section once all relevant data has been entered.

Click to expand
Project Image
Outage Info Screen 2

The current screen bears a strong resemblance to the previous one, with the notable addition of the navigation bar unlocking the option to select the impact statement for review while still retaining the ability to take action on this screen. An important detail to highlight from the previous screen is that once information is submitted, all data becomes locked, including the name of the individual who entered the information, for auditing purposes. This ensures that any revisits to the screen only allow viewing of the submitted impact statements.


A significant effort was invested in perfecting this particular section. When a user submits an outage, they list all affected buildings, which are displayed here. The staff member responsible for this section inputs the custodian's email address, unless the building corresponds to one in another data source, in which case the custodian's information is auto-filled.


Upon selecting the submit button, the tool sends a notification confirming that the email has been dispatched. Once the custodian either approves or rejects the request and provides a reason, this action is reflected in the application, as depicted above. Additional functionalities include the ability to add extra buildings, send notifications collectively or individually, edit, delete.


Upon receiving approval from all building custodians for the outage to proceed, the subsequent section will automatically become accessible.

Click to expand
Project Image
Outage Info Screen 3

This simplistic screen serves the purpose of indicating that the following section has been unlocked, while still allowing access to the other two sections. Once all the required information has been entered into these boxes, the subsequent area will become accessible.

Click to expand
Project Image
Outage Info Screen 4

This final screen is intentionally kept simple, providing essential details about the request, including information on when the 5-day reminder is dispatched. Additionally, it offers the functionality to close the outage and archive it.

Click to expand
Project Image
Approval Email Flow

Upon activation by the staff's selection of the send button, this workflow manages approval emails. It initiates by retrieving items from the data source which contains building information.


The workflow then generates a document consolidating the input provided by GC and BT, formatting it appropriately. This document is automatically dispatched to the designated custodians.


Following this, the workflow awaits approval or rejection of the request. Upon completion of this stage, it updates the data source, consequently refreshing the view seen by administrators.

Task Tracker

Click to expand
Project Image
Create a task screen 1

First of all we can see that again this is part of the tasking tool project continuing with the theme but this is still a notable mention do it, it functioning differently to the previously mentioned projects.


n the administrative section of the application, staff can conveniently submit tickets for various tasks. The interface is designed intuitively, with a notable feature being the navigation bar positioned on the right-hand side. This navigation bar operates similarly to the one implemented in the outage tracker project, ensuring consistency across different functionalities.


A key highlight of this section is the recurring task feature, which plays a crucial role in managing jobs that require regular attention on a daily, weekly, or monthly basis. Implementing this functionality posed a challenge that demanded an extended period of focus and effort.


However, the process of overcoming this challenge not only enhanced my understanding of the system but also significantly improved the overall performance of the feature. This experience served as a valuable learning opportunity, allowing me to leverage my expertise effectively to achieve seamless functionality within the application.

Click to expand
Project Image
Create a task screen 2

This section represents the subsequent page within the task submission interface, empowering employees to generate an unlimited number of checklist items tailored to their specific tasks. The versatility of this feature becomes evident when navigating through the task overview screen, where the effectiveness of these checklists truly shines.


Additionally, users have the capability to establish deadline dates for each task, enhancing the organization and prioritization of assignments within the application.

Click to expand
Project Image
Create a task screen 3

Displayed here is the conclusive confirmation page, clearly labelled as such in the navigation bar for easy identification. Once the staff member has reviewed and finalized their inputted information for the task, a pivotal decision awaits them – the assignment of the task. Positioned on the right-hand side of the screen is the option to assign the task to all personnel, offering a convenient and efficient distribution method.


However, it is important to note that not all users possess the authority to assign tasks to the entire workforce. This privilege is reserved for specific managers within the department who hold the responsibility of delegating tasks to other teams and individuals. This hierarchical structure ensures that task assignments are managed effectively and in alignment with the organizational hierarchy.

Click to expand
Project Image
View taskings

This page serves as the central hub for viewing task assignments, presenting a well-organized layout that encapsulates all the essential information provided by the staff members. The checklist feature is prominently displayed, offering a comprehensive overview of tasks and enabling seamless modifications through the edit function. Users can effortlessly add, remove, or adjust checklist items to streamline task completion, enhancing efficiency and productivity.


Moreover, the functionality of various buttons remains consistent across the interface, including options for comments, reminders, reassignment, marking tasks as completed, and editing task details. This uniformity in button operations ensures a user-friendly experience and facilitates smooth navigation within the application.


This tool plays a pivotal role in our workplace dynamics, particularly in scenarios where task assignments originate from sources other than direct user inputs. The system's capability to track and manage such tasks is invaluable, contributing significantly to task completion and overall operational efficiency.


Furthermore, this feature proves instrumental in facilitating seamless transitions during hand-over situations, allowing staff members to transfer ongoing tasks to their counterparts efficiently, thereby ensuring timely and uninterrupted task completion.