Skip to main content

Build an Overtime Timesheet App in Power Apps — Part 5: Build the Home Screen

· 27 min read
Jagdish Kumawat
Founder @ Dewiride

The app gets its first real screen in this part. The Home screen greets the signed-in person, shows their department and, if they approve overtime, which departments they approve for. Its tiles depend on the person's role: everyone can log overtime, but only approvers, payroll staff and admins see the screens meant for them.

This is Part 5 of a 20-part series.

  1. Part 1: Plan the App and Set Up the Demo Organization
  2. Part 2: Create the SharePoint Site and Lists
  3. Part 3: Keep Overtime Private with SharePoint Permissions
  4. Part 4: Create the Solution, Environment Variables and Canvas App
  5. Part 5: Build the Home Screen (you are here)
  6. Part 6: Build the Log Overtime Screen
  7. Part 7: Build the My Overtime Screen
  8. Part 8: Build the Approval Flow for Teams and Outlook
  9. Part 9: Show Approvers What's Waiting (coming soon)
  10. Part 10: Build the Departments Screen (coming soon)
  11. Part 11: Build the Reports Screen (coming soon)
  12. Part 12: Import the Old Excel Timesheet (coming soon)
  13. Part 13: Create the Monthly Payroll Workbook with Office Scripts (coming soon)
  14. Part 14: Build the Power BI Overtime Report (coming soon)
  15. Part 15: Share the App and Add It to Microsoft Teams (coming soon)
  16. Part 16: Test Every Role and Department (coming soon)
  17. Part 17: Build a Setup Flow That Creates the Lists (coming soon)
  18. Part 18: Run the Solution Checker and Export the Solutions (coming soon)
  19. Part 19: Install the App in a New Environment (coming soon)
  20. Part 20: Recap, Production Checklist and Next Steps (coming soon)

Part 4 left an empty app connected to the lists. This part decides how the app recognizes each role, writes that down once as named formulas, and builds the screen on top. Each generic task has its own guide; this part gives the values for this app, and why.

What You'll Build​

WhoHow the app knowsTiles they see
EveryoneSigned inLog overtime, My overtime
ApproversNamed in a department's Approvers columnPlus Waiting for approval and Reports
Payroll staffMembers of the Overtime Payroll groupPlus Reports
AdminsMembers of the Overtime Admins groupPlus Departments

The tiles don't open anything yet: each later part builds a screen and points its tile at it.

Prerequisites​

How the App Recognizes Each Role​

Three roles, three sources of truth:

  • Approvers are already in SharePoint: Part 2's Departments list names each department's approvers in its Approvers column. The app checks whether the signed-in person's email is in that column for any active department.
  • Payroll staff and admins are the members of two security groups from Part 1, Overtime Payroll and Overtime Admins. The standard Office 365 Groups connector lists a group's members.
  • The groups' IDs differ for every organization that installs the app, so they can't be typed into formulas. Environment variables would be the usual home for them, but the documented way for a canvas app to read a text environment variable is the Dataverse connector, which is premium, and this app runs on standard licenses. They go in a small SharePoint list, Settings, instead: How to Store App Settings in a SharePoint List for Power Apps explains the choice.

Showing or hiding a tile doesn't protect anything: Part 3's SharePoint permissions do that. The tiles only keep the app tidy for each role.

Step 1: Create the Settings List​

On the Overtime Timesheet site, follow How to Store App Settings in a SharePoint List for Power Apps, Steps 1 to 6:

SettingValue
List nameSettings, not in the site navigation
ColumnsTitle, required and unique; Value, single line of text, required
List descriptionSettings for the Overtime Timesheet app, such as the IDs of the payroll and admins groups. Only site owners can change them.
PermissionsUnique: Overtime Timesheet Owners with Full Control, Overtime Timesheet Visitors with Read
ItemsPayrollGroupId and AdminsGroupId, each with its group's Object ID

The Object IDs come from each group's Overview in Microsoft Entra: How to Find a Group's Object ID in Microsoft Entra. Staff can read the list through Visitors, as Part 3 set up for the whole site, and only owners can change it. The list holds both settings (IDs masked):

The Settings list with the columns Title and Value and two items, AdminsGroupId and PayrollGroupId, each with a masked Object ID

Step 2: Add an Environment Variable for the List​

Open the Overtime Timesheet solution and add a fifth variable, as in Part 4, with How to Create Environment Variables for a SharePoint Site and List in Power Apps:

Display nameNameParameter TypeSiteCurrent listDescription
Settingsdewiride_SettingsListListOvertime Timesheet SiteSettingsThe SharePoint list of app settings, such as the IDs of the payroll and admins groups.

The New environment variable panel with Display name Settings, Name dewiride_SettingsList, the description, Data Type Data source, Connector SharePoint, Connection admin@example.com, Parameter Type List, Site Overtime Timesheet Site and Current list Settings, both outlined in red

Leave Default Value empty, like the others, so whoever installs the solution chooses their own list.

Step 3: Add the Settings List and Office 365 Groups to the App​

Open the app in Studio from the solution and add two data sources:

  1. Settings, through its variable: How to Connect a Canvas App to SharePoint Lists with Environment Variables. Choose Overtime Timesheet Site on the Advanced tab, then tick Settings on the second Advanced tab:

The Choose a list panel on its Advanced tab, Connect using an existing environment variable, with Departments, OvertimeEntries and Payroll Exports unticked and Settings ticked, outlined in red, and the Connect button outlined in red

  1. Office 365 Groups: How to Add the Office 365 Groups Connector to a Canvas App in Power Apps. It's a standard connector, so the app's license designation stays Standard.

The Data pane now lists five sources:

The Data pane listing Office365Users, the SharePoint lists Departments, OvertimeEntries and Settings, and Office365Groups, outlined in red

Step 4: Write the Named Formulas​

Named formulas are values the whole app can use, calculated when something needs them (How to Use Named Formulas in Power Apps). Select App in the Tree view, choose Formulas in the property list, and enter these, in four groups.

The app and the person:

App → Formulas (1 of 4)
AppTitle = "Overtime Timesheet";
MyProfile = Office365Users.MyProfileV2({'$select': "id,displayName,givenName,mail,userPrincipalName,jobTitle,department"});
MyEmail = Coalesce(MyProfile.mail, MyProfile.userPrincipalName);
MyDepartment = Trim(MyProfile.department);
  • AppTitle is the header's text, in one place.
  • MyProfile reads the person's Microsoft 365 profile once, only the fields the app uses, including id for the group checks and department for the screen: How to Get the Current User's Profile and Job Title in Power Apps (MyProfileV2).
  • MyEmail falls back to the sign-in name for an account without an email address (Coalesce).
  • MyDepartment drops stray spaces from the profile's department, so it matches the Departments list later (Trim).

Approvers, from the Departments list:

App → Formulas (2 of 4)
MyApproverDepartments = With(
{ActiveDepartments: Filter(Departments, IsActive = true)},
Concat(Filter(ActiveDepartments, MyEmail in Approvers.Email), Department, ", ")
);
IsApprover = !IsBlank(MyApproverDepartments);

SharePoint returns the active departments, and the app checks each one's Approvers for the person's email. The result is text, the names of the departments they approve, and IsApprover is true when it isn't blank: How to Check If the Current User Is in a SharePoint Person Column in Power Apps.

My first version was a single Filter(Departments, IsActive = true, MyEmail in Approvers.Email) returning a table, and Studio raised two delegation warnings. Each has its own post, with what I checked and why the version above clears it:

The group IDs, from the Settings list:

App → Formulas (3 of 4)
PayrollGroupId = LookUp(Settings, Title = "PayrollGroupId").Value;
AdminsGroupId = LookUp(Settings, Title = "AdminsGroupId").Value;

Payroll and admins, from the two groups:

App → Formulas (4 of 4)
IsPayroll = IfError(
MyProfile.id in Office365Groups.ListGroupMembers(PayrollGroupId, {'$top': 999}).value.id,
false
);
IsAdmin = IfError(
MyProfile.id in Office365Groups.ListGroupMembers(AdminsGroupId, {'$top': 999}).value.id,
false
);

Each asks for up to 999 of the group's members and checks whether the person's ID is among them. If anything fails, such as a missing setting, the answer is false, so the app shows less rather than more: How to Check If the Current User Is in a Security Group in Power Apps.

Here's all of App.Formulas:

A macOS-style code window titled App → Formulas showing the eleven named formulas: AppTitle, MyProfile, MyEmail, MyDepartment, MyApproverDepartments with With and Concat, IsApprover, PayrollGroupId, AdminsGroupId, IsPayroll and IsAdmin with IfError and ListGroupMembers

App → Formulas
AppTitle = "Overtime Timesheet";
MyProfile = Office365Users.MyProfileV2({'$select': "id,displayName,givenName,mail,userPrincipalName,jobTitle,department"});
MyEmail = Coalesce(MyProfile.mail, MyProfile.userPrincipalName);
MyDepartment = Trim(MyProfile.department);
MyApproverDepartments = With(
{ActiveDepartments: Filter(Departments, IsActive = true)},
Concat(Filter(ActiveDepartments, MyEmail in Approvers.Email), Department, ", ")
);
IsApprover = !IsBlank(MyApproverDepartments);
PayrollGroupId = LookUp(Settings, Title = "PayrollGroupId").Value;
AdminsGroupId = LookUp(Settings, Title = "AdminsGroupId").Value;
IsPayroll = IfError(
MyProfile.id in Office365Groups.ListGroupMembers(PayrollGroupId, {'$top': 999}).value.id,
false
);
IsAdmin = IfError(
MyProfile.id in Office365Groups.ListGroupMembers(AdminsGroupId, {'$top': 999}).value.id,
false
);

Open Variables (the {x} icon on the left) to see their values for you. For the maker, IsAdmin is true, IsApprover and IsPayroll are false, and MyDepartment is Management (the IDs and email are masked here):

The Named formulas section of the Variables pane: AdminsGroupId as masked text, AppTitle Overtime Timesheet, IsAdmin true, IsApprover false, IsPayroll false, MyApproverDepartments empty text, MyDepartment Management, MyEmail admin@example.com, MyProfile as a record, and PayrollGroupId as masked text

note

In the example, after Format text in the expanded formula bar, the editor went blank, and later App.Formulas was missing the two approver formulas. Leaving Studio, opening the app again and entering the formulas once more fixed it; I didn't find the cause. Read the whole list once more before you save.

Step 5: Rename the Screen and Make It the Start Screen​

Rename Screen1 to Home Screen (How to Rename a Screen or Control in Power Apps):

The Tree view with the Screens tab, App, and the screen Home Screen outlined in red

Screen readers announce a screen's name when it opens, and the App checker suggests a better one while it's still Screen1: Fixed: "Revise Screen Name" in the Power Apps App Checker. Then select App and set StartScreen (How to Set the Start Screen in Power Apps with App.StartScreen):

App → StartScreen
'Home Screen'

The app opens on the Home screen whatever screens later parts add.

Step 6: Build the Layout​

Containers arrange the controls and resize with the window. This is the screen's tree, with the suffix HS for Home Screen on every name (Power Apps Naming Conventions for Screens, Controls and Formulas):

Home Screen layout
Home Screen
└─ conMainHS vertical: fills the screen
├─ conHeaderHS horizontal: the header
│ └─ lblTitleHS the app's name, the screen's main heading
└─ conBodyHS vertical: everything below the header
├─ conProfileHS horizontal: the profile row
│ ├─ avtMeHS initials or photo
│ └─ conProfileTextHS vertical: the lines of text
│ ├─ lblWelcomeHS
│ ├─ lblDepartmentHS
│ └─ lblApproverHS
└─ conActionsHS horizontal: the tiles, wrapping on phones
├─ btnLogOvertimeHS
├─ btnMyOvertimeHS
├─ btnApprovalsHS
├─ btnReportsHS
└─ btnDepartmentsHS

The containers. Insert each one inside its parent and rename it:

ContainerTypeSettings
conMainHSVerticalX, Y 0; Width Parent.Width; Height Parent.Height; Align (horizontal) Stretch; Padding 0; Drop shadow None; Border radius 0
conHeaderHSHorizontalFlexible height Off, Height 64; Fill App.Theme.Colors.Primary; Align (vertical) Center; Padding left and right 24, top and bottom 0; Drop shadow None; Border radius 0
conBodyHSVerticalFlexible height On; Align (horizontal) Stretch; Gap 16; Padding 24; Vertical overflow Scroll; Drop shadow None; Border radius 0
conProfileHSHorizontalFlexible height Off, Height from the formula below; Gap 16; Align (vertical) Center; Padding 0; Drop shadow None; Border radius 0
conProfileTextHSVerticalFlexible width On, fill portions 1; Gap 4; Align (horizontal) Stretch; Justify (vertical) Center; Padding 0; Drop shadow None; Border radius 0
conActionsHSHorizontalFlexible height On, fill portions 1; Gap 16; Align (vertical) Start; Horizontal and Vertical overflow Hide; Wrap On; Padding 0; Drop shadow None; Border radius 0

The header's color is the theme's main color, so it follows the theme in Step 7 (How to Use Theme Colors and Fonts in Power Apps Formulas). The body scrolls when it doesn't fit. The tiles' row fills the rest of the screen and moves tiles onto new rows when they don't fit across: How to Wrap Controls onto the Next Row in a Horizontal Container in Power Apps.

The heading. Inside conHeaderHS, insert Classic → Text label, lblTitleHS. It's the classic label because it has Role, which tells screen readers this is the screen's main heading: How to Add a Heading for Screen Readers in Power Apps.

PropertyValue
TextAppTitle
RoleTextRole.Heading1, set in the formula bar
ColorColor.White
FontApp.Theme.Font
SizeIf(App.ActiveScreen.Size = ScreenSize.Small, 18, 20)
FontWeightFontWeight.Semibold
Flexible widthOn, fill portions 1
Height40
PaddingLeft0
TabIndex-1

The profile row. Inside conProfileHS, insert Display → Avatar, avtMeHS (How to Add an Avatar Control in Power Apps):

PropertyValue
ImageIf(Office365Users.UserPhotoMetadata(User().Email).HasPhoto, User().Image)
NameUser().FullName
BadgeBlank()
Width, Height72, 72
AccessibleLabel"Profile picture of " & User().FullName

The Image formula uses a photo only when there is one, so people without a photo see their initials, not a grey person icon: Fixed: Power Apps Avatar Shows Grey Person Icon Instead of Initials.

Inside conProfileTextHS, insert three Display → Text controls (How to Add a Text Control in Power Apps) with Auto height on and AccessibleLabel Self.Text:

lblWelcomeHS → Text (Size 24, FontWeight Semibold)
"Welcome, " & Coalesce(MyProfile.givenName, MyProfile.displayName)
lblDepartmentHS → Text
If(
IsBlank(MyDepartment),
"Your Microsoft 365 profile has no department. You can still choose one each time you log overtime.",
"Department: " & MyDepartment
)
lblApproverHS → Text
"You approve overtime for " & MyApproverDepartments & "."
lblApproverHS → Visible
IsApprover

A profile without a department gets a sentence instead of an empty line (If), and the approver line shows only for approvers (Visible).

conProfileHS has a fixed height, so it needs a formula that grows with its text, and leaves out the approver line when it's hidden:

conProfileHS → Height
Max(
avtMeHS.Height,
lblWelcomeHS.Height + lblDepartmentHS.Height + conProfileTextHS.LayoutGap
+ If(lblApproverHS.Visible, lblApproverHS.Height + conProfileTextHS.LayoutGap, 0)
)

Max takes the larger of the avatar and the text column (How to Get the Largest Value in Power Apps with Max). Without it, wrapped text on a phone would be cut off: Fixed: Text Cut Off Inside a Container on Small Screens. For the maker, with the approver line hidden, it comes to 79.

The tiles. Inside conActionsHS, add two buttons, btnLogOvertimeHS and btnMyOvertimeHS, and set them up. Then copy btnMyOvertimeHS and paste it three times for the role tiles, renaming each copy (How to Copy and Paste Controls Between Screens in Power Apps):

ButtonTextIconAppearanceVisibleAccessibleLabel
btnLogOvertimeHS"Log overtime""CalendarAdd"Primarytrue"Log overtime: add the extra hours you worked"
btnMyOvertimeHS"My overtime""History"Secondarytrue"My overtime: your entries and totals"
btnApprovalsHS"Waiting for approval""TextBulletListSquareClock"SecondaryIsApprover"Waiting for approval: overtime that needs your decision"
btnReportsHS"Reports""ArrowTrending"SecondaryIsApprover || IsPayroll"Reports: overtime totals by department, person and month"
btnDepartmentsHS"Departments""Building"SecondaryIsAdmin"Departments: add or change departments and their approvers"

Every tile also gets:

PropertyValue
WidthIf(App.ActiveScreen.Size = ScreenSize.Small, Parent.Width, 200)
Height40
OnSelectfalse

Before the theme, the screen is in the default Power Apps blue. The maker sees three tiles: the two for everyone, and Departments, because they're in Overtime Admins:

Studio's Themes pane with Power Apps selected, next to the Home screen in blue: the Overtime Timesheet header, the AU avatar, Welcome, Admin, Department: Management, and the tiles Log overtime, My overtime and Departments

Step 7: Apply the Green Theme​

Follow How to Apply a Modern Theme in Power Apps and select Green. Studio asks whether to Apply to classic controls; select Cancel, because the only classic control, lblTitleHS, takes its color and font from the formulas above. The header, the avatar and the Log overtime tile turn green together, because their colors come from the theme:

Studio's Themes pane with Green outlined in red, next to the Home screen in green: the header, the AU avatar and the Log overtime tile now green

App.Theme is now GreenTheme.

Step 8: Check the Roles​

Select a tile and its Visible formula shows the value for you. For btnDepartmentsHS, IsAdmin = true, and the tile is on the screen:

The formula bar with btnDepartmentsHS Visible set to IsAdmin, the preview strip reading IsAdmin = true with Data type boolean, and the Home screen with the Departments tile selected next to Log overtime and My overtime

The maker isn't an approver or in payroll, so Waiting for approval and Reports stay hidden, and so does the approver line. To see the formulas give the right answer for an approver without signing in as one, How to Check If the Current User Is in a SharePoint Person Column in Power Apps uses Olivia Bennett's email for a moment and gets Emergency Department. Part 16 signs in as every persona and checks each one's screen.

Step 9: Check the Screen on a Phone​

Preview the app with F5 (How to Preview a Canvas App in Power Apps Studio) and choose Apple iPhone 12, 13, 14 (How to Test a Power Apps Canvas App on Phone and Tablet Sizes). The title is smaller, and the tiles wrap into one full-width column:

A phone preview of the Home screen: the green Overtime Timesheet header, the AU avatar with Welcome, Admin and Department: Management, and the Log overtime, My overtime and Departments tiles stacked at full width

Step 10: Run the Accessibility Check​

Open the App checker and select Accessibility. It lists two errors, both on the heading, lblTitleHS:

The Accessibility page of the App checker with Errors (2): Focus isn't showing (1) on lblTitleHS and Missing tab stop (1) on lblTitleHS

Leave both as they are. The heading isn't something to select, so it shouldn't take a place in the keyboard's Tab order, and Microsoft's guidance for labels that aren't interactive is TabIndex -1. The two posts explain each error and why a heading keeps it:

Data source (1) is OvertimeEntries, which no formula uses until Part 6: Fixed: "Unused Data Sources" in the Power Apps App Checker. Formulas has no count.

Step 11: Save the App​

Select Save. Don't publish yet: nobody else can open the app until Part 15 shares it. Here's the finished Home screen on the canvas:

The finished Home screen in Studio: the green Overtime Timesheet header, the AU avatar, Welcome, Admin, Department: Management, and the Log overtime, My overtime and Departments tiles

And its controls in the Tree view, matching the layout from Step 6:

The Tree view: App, then Home Screen with conMainHS, conHeaderHS with lblTitleHS, conBodyHS with conProfileHS (avtMeHS and conProfileTextHS with lblWelcomeHS, lblDepartmentHS and lblApproverHS) and conActionsHS with btnLogOvertimeHS, btnMyOvertimeHS, btnApprovalsHS, btnReportsHS and btnDepartmentsHS

Common Mistakes​

MistakeWhat happensDo this instead
Typing the group IDs into the formulasEvery organization that installs the app has to edit itKeep them in the Settings list
Leaving Members able to edit SettingsAnyone in Members can change who counts as payroll or adminOwners only, as in Step 1
Filtering Departments with in directlyDelegation warnings, and missed departments past 500 itemsUse the With version from Step 4
Leaving id out of MyProfile's '$select'IsPayroll and IsAdmin are always falseSelect id
Relying on hidden tiles for privacyThe data is still open to anyone SharePoint lets inKeep Part 3's permissions
A fixed Height on conProfileHSText is cut off on phonesUse the Max formula

Troubleshooting​

SymptomLikely causeFix
Departments doesn't show for an adminAdminsGroupId is blank or wrong, or the person isn't a direct memberCheck the Settings item and the group's Members
IsApprover is false for an approverThe department's IsActive is No, or the emails differCheck the department, then compare MyEmail with Approvers
The approver line shows a blank departmentlblApproverHS's Visible isn't IsApproverSet Visible to IsApprover
Tiles run off the edge of a phoneWrap is off on conActionsHSTurn it on
Settings is underlined red in a formulaThe list isn't in the appAdd it as in Step 3

FAQ​

Why does the maker see the Departments tile?​

Because the maker is in Overtime Admins, as Part 1 set up. By the same formulas, Leo Martin, the payroll officer, gets Reports instead, and Olivia Bennett and Daniel Brooks, the approvers, get Waiting for approval and Reports. Part 16 signs in as each of them to confirm it.

Where's this month's total?​

On the My Overtime screen, which Part 7 builds with each person's entries and totals. The Home screen stays a quick menu.

Why named formulas and not App.OnStart?​

Named formulas are calculated when something needs them, so the screen doesn't wait for every lookup before it opens, and each value is defined once for the whole app. How to Use Named Formulas in Power Apps compares the two.

Does this need premium licenses?​

No. SharePoint, Office 365 Users and Office 365 Groups are standard connectors, and the app's license designation stays Standard.

Conclusion​

The app now opens on a Home screen that knows who you are:

  • a Settings list with the payroll and admins group IDs, editable only by site owners, and a fifth environment variable for it;
  • the Office 365 Groups connector, and named formulas for the person, their department and their roles: IsApprover from the Approvers column, IsPayroll and IsAdmin from the groups;
  • a responsive layout whose tiles depend on the role and wrap into one column on phones, in the Green theme.

Part 6 builds the first screen behind a tile: Log overtime, with dates, times, breaks and the hours worked out as you type.

Additional Resources​

← Previous: Part 4: Create the Solution, Environment Variables and Canvas App Next → Part 6: Build the Log Overtime Screen