Table of Contents
Create A Employee Timesheet Using Formidable Forms
This article assumes that you are using the latest version of Formidable Pro and know how to add PHP snippets to your site. Along with a basic understanding of HTML and CSS.
The employee timesheet application consists of three key parts:
1. A form for entering the dates and times worked of employee.
2. A filter form for filtering the dates viewable (optional) & by staff members.
3. A view for displaying the employee logs.
We built this application using the following steps:
Step 1: Build the initial form for our staff timesheet
Firstly, we need to create the entry form. The entry form consists of:
1. A date field to capture the date being entered.
2. 2 time fields to capture the start and end times.
3. A text field to indicate the length of a lunch break. In this instance the time is fixed to one hour, so it’s safe to leave this as a read-only field but you can adjust as required.
4. A toggle field to switch the annual leave status.
5. A hidden field which will calculate the time worked for each entry.
Once we have the form we need to add a PHP snippet to our functions.php file, a custom plugin file or using the Code Snippets plugin.We have edited to the snippet provided by the Formidable Team (foundHERE) to include the lunch hour and remove this from the total hours worked:
add_filter('frm_validate_field_entry', 'calculate_worktime', 11, 3);
function calculate_worktime($errors, $field, $value){
if($field->id == 1900){ //change 26 to the ID of the hidden or admin only field which will hold the calculation
$rep_section = $_POST['item_meta'][1904];
unset($rep_section["form"]);
unset($rep_section["row_ids"]);
$x1 = 0;
$x2 = 0;
$totaltimes = array();
$totaltime1 = array();
foreach($rep_section as $rep=> $val){
unset($rep[0]);
unset($rep[1899]);
$x1 = (strtotime($val[1895]));
$x2 = (strtotime($val[1896]));
$start = $x1;
$end = $x2;
$lunch = (strtotime($_POST['item_meta'][1897])); //change 25 to the ID of the lunch hour field
$totaltime = ($end - ($start + $lunch));
$hours = intval($totaltime / 3600);
$seconds_remain = ($totaltime - ($hours * 3600));
$minutes = intval($seconds_remain/ 60);
//$seconds = ($seconds_remain - ($minutes * 60)); Uncomment this line if you want seconds calculated.
$leading_zero_for_minutes = $minutes < 10 ? '0' : '';
//$leading_zero_for_seconds = $seconds < 10 ? '0' : '';//Uncomment this line if you're including seconds.
$totaltimes[] = $hours . ':' . $leading_zero_for_minutes . $minutes;
}
$totaltime = implode("
", $totaltimes);
$value = $_POST['item_meta'][1900] = $totaltime; //change 26 to the ID of the hidden or admin only field which will hold the calculation
}
return $errors;
}
The above code will execute when the form is submitted and add calculate the numbers of hours worked and save it to the hidden field. This could also be done on the fly using JS if required.
Step 2: Build the Search form for our staff timesheet
- A date field for the start date
- A date field for the end date
In the form settings we set the following options:
1. Select “Do not store entries submitted from this form”
2. Change the ‘On Submit’ option to ‘Redirect to URL’
3. In the URL enter www.YourSite.com/YourView/?start_date=[551]&end_date=[552] and change 552 and 553 to the ID’s of your 2 date fields.
Step 3: Building Your View
In our view, under basic settings, we have selected Form 1 (our time sheet form) and ‘All Entries’ as the view type. Our view has been set up as an html table, but you may wish to build yours differently.
Adding a URL Parameter
We have also added an additional snippet to our functions.php file to allow us to use the ‘if_get_param’ variable and display page content based on a URL parameter. To do this please add the following script to your functions.php file, a custom plugin file or using the Code Snippets plugin.
/* Add Formidable Get-Param Shortcode */
add_shortcode('if_get_param', 'check_get_param_value');
function check_get_param_value( $atts, $content="" ) {
if ( ! isset( $atts['name'] ) || ! isset( $atts['value'] ) || ! isset( $atts['type'] ) ) {
return $content;
}
$type = $atts['type'];
if ( $type == 'greater_than' ) {
$type = '>';
} else if ( $type == 'less_than' ) {
$type = '<';
} else if ( $type == 'equals' ) {
$type = '==';
} else if ( $type == 'not_equal' ) {
$type = '!=';
}
$get_value = isset( $_GET[ $atts['name'] ] ) ? $_GET[ $atts['name'] ] : '';
if ( ! FrmFieldsHelper::value_meets_condition( $get_value, $type, $atts['value'] ) ) {
$content = '';
}
return do_shortcode( $content );
}
This will then allow you to use the following shortcode. For more information on this please click HERE:
[ if_get_param name="Whatever" type="not_equal" value="" ]Your Content Here[ /if_get_param ]
Adding a search filter to the view
Then, in the ‘Before Content’ section we have added the following code:
[ if_get_param name="start_date" type="not_equal" value="" ]
Filter: [ get param="start_date"] - [ get param="end_date"]Clear Filter
[ /if_get_param ]
This shortcode will display the content of the search filter and provide a ‘Clear Filter’ link to easily reset the filter. Change Clear Filter to the URL of your view.
The View
We will then add the following directly underneath in the Before Content section:
<script src="https://www.YourSite.Com/table-export.js"></script>
<div style="overflow-x:auto;">
<table>
<thead>
<tr>
<th>Employee Name</th><td>[first_name] [last_name]</td>
<th>Department</th><td>[user_meta key=description]</td>
<th>Week beginning</th><td colspan="2">[get param="start_date"]</td>
</tr>
<tr style="visibility: hidden;"><td colspan="7"></td></tr>
<tr>
<th class="dateFormat-dd/mm/yyyy">Date</th>
<th>Start Time</th>
<th>Lunch</th>
<th>End Time</th>
<th>Hours Worked</th>
<th>AL?</th>
<th>Actions</th>
</tr>
</thead>
Then in the main content of the view we will add the following:
<tr>
<td>[if 606 equals="Yes"]<span style="color: #e03c83;">[546 format="d/m/y"]</span>[/if 606][if 606 not_equal="Yes"][546 format="d/m/y"][/if 606]</td>
<td>[if 606 equals="Yes"]<span style="color: #e03c83;">[541]</span>[/if 606][if 606 not_equal="Yes"][541][/if 606]</td>
<td>[if 606 equals="Yes"]<span style="color: #e03c83;">[543]</span>[/if 606][if 606 not_equal="Yes"][543][/if 606]</td>
<td>[if 606 equals="Yes"]<span style="color: #e03c83;">[542]</span>[/if 606][if 606 not_equal="Yes"][542][/if 606]</td>
<td>[if 606 equals="Yes"]<span style="color: #e03c83;">[544]</span>[/if 606][if 606 not_equal="Yes"][544][/if 606]</td>
<td>[if 606 equals="Yes"]<span style="color: #e03c83;">[606]</span>[/if 606][if 606 not_equal="Yes"][606][/if 606]</td>
<td>[editlink location="front" label="Edit" page_id=7806] | [deletelink label="Delete"]</td>
</tr>
Then in the ‘After Content’ section of the view we will add the following:
<tr style="visibility: hidden;"><td colspan="7"></td></tr>
</tfoot>
<tr>
<th></th>
<th></th>
<th></th>
<th style="text-align: right;">Total Hours:</th>
<th>[sum_544]</th>
<th colspan="2"></th>
</tr>
</tfoot>
</table>
</div>
In order to calculate the total time worked for the numbers of rows on display in the table, we have created a new code snippet that will create a total of the hidden fields from Form 1 and add display them in a shortcode – [sum_544] – in the ‘After Content’ section of the view.
Export to CSV
Lastly, we need to add a button which would allow the user to export the view table content into a CSV format.
Add this button to the After Content section, under the table html:
<div style="display: block; margin: 20px auto; width: fit-content;">
<button onclick="exportTableToCSV('TimeSheet_[get param="start_date"]_[get param="end_date"].csv')" class="nectar-button small see-through-2 has-icon" style="cursor: pointer; padding: 10px 33px; margin-top: 25px; visibility: visible; color: rgb(0, 0, 0); border-color: rgba(0, 0, 0, 0.75); background-color: transparent;" data-color-override="false" data-hover-color-override="false" data-hover-text-color-override="#ffffff"><span>DOWNLOAD TIMESHEET</span><i class="fa fa-download" style="color: rgb(255, 255, 255);"></i></button>
</div>
In the Advanced Settings section of our view we then have the following settings:
1. Page size = 31 – This will allow us to show a maximum of 31 entries at any time which will be enough for any full month once the filters have been applied.
2. Order > Date > Descending – Adjust as required.
3. Filter Entries – We have 3 filters on our view:
1. User ID is Equal to > Current User
2. Date is Greater than or equal to > [ get param=”start_date” ]
3. Date is Less than or equal to > [ get param=”end_date” ]
These settings, along with the filter form mentioned above, will allow you to filter your view based on any date range. If you require an admin only view to view all staff working hours, remove the User ID filter.
Step 4: Building your page
[ formidable id=48 ] – The timesheet form
[ formidable id=49 ] – The filter / search form
[ display-frm-data id=7808 filter=limited ] – the view for displaying your data.