I’m working on a project right now for a company. They would like to add a punch clock to an internal use application I wrote, which will be used by their employees to submit their time sheets.
- Employees must be able to punch in and out easily
- Employees should be able to add/edit/delete their own (and only their own) punches within the last 14 days
- Admin users should be able to add/edit/delete any employees punches, indefinitely
- Admin users should be able to report on employee punches, with date parameters
- Admin users should be able to export the report into a CSV file
This is a fairly small addon to the application - so I think we can get away with having just a few small components.
We already have a user, which comes built in with Laravel. In the past, we added an
is_admin boolean field.
punch model doesn’t need to be too complicated for our needs. The way I see it, we’ll have
user_id- the foreign key to the users table
in_at- UTC timestamp for time the punch occurred
out_at- the UTC timestamp for the time the punch out occurred
duration- integer representing the number of minutes for the shift
I think it makes sense to break duration out like this for a few reasons.
a) it’s going to be easier on the database to run the sum of this column, as opposed to the sum of the date diff between the two fields
b) if we want to do any manipulations to the time (eg, rounding to the closest 15 minutes) that’ll be easier to do in this setup.
After we define this, it’s probably safe to make all the fields fillable for this application.
We’re also going to want to define a few relationships for this new model. 1
user can have many
punch’s, so we’ll
need to define
We also will probably need some scopes for the punch
inProgress- a model scope for punches that have an
in_atvalue, but no
out_atvalue yet - this will make it easier to determine a users current status
completed- a model scope for punches that have both an
in_atvalue, and an
We also need to define some local attributes (this is a personal preference) which converts the stored UTC time into the local timezone
and the mutators for setting the time, which takes the local time, converts it to UTC, and then saves it
Now, once all this is done, we also need to make sure we protect the administration pages, so we also need to define &
So - what we need for this portion of the work is the following.
- 1 new model & migration for
- define scope for
- define the local accessor and mutator for
- define the local accessor and mutator for
- define & register
PunchPolicyto protect unauthorized users from editing/accessing other records
The way that the employees will use the punch clock is probably the most important factor on the front end.
So I’m thinking we need to do a navigation bar widget where the users can punch in & out, without having to go to a different screen.
This application is written with Jetstream, we already have some great tailwind menu components that we’ll repurpose/copy, and because it’s responsive, we’ll actually need 2 components, one for the mobile view, and one for the desktop view.
After that, we’ll need to make a page where users can manage their punches, we could combine this with the admin/report, but I think it probably makes more sense to seperate them out, because there is enough different functionality between them (eg. filters, export functionality). So we’ll break the list of punches into 2 components, one for admins, and one for a user perspective.
Lastly, we need an edit punch, which will also provide the delete functionality. I’m probably going to make use of
<x-jet-form-section> component from Jetstream for this page.
So for this we’ll need to make these livewire components
- 1 model (3 fields, 1 relationship, 1 policy, 2 scopes, 2 mutators/accessors)
- 2 in-page component (same component, 1 for mobile, 1 for desktop, both with 1 function)
- a full-page component for listing the model, no filters, but has a quick-add form
- a full-page component for listing the model, with filters, quick-add form, and export functionality
- a full-page component for editing the model
The purpose of me documenting this work is to improve my estimation ability on time taken on implementing a project
|Planning||2hr 30 min|
|Model creation (w/ relationships, accessors, mutators, policy)||30 min|
|Desktop & mobile quick-punch nav components||22 min|
|Full page, employee list component||58 min|
|Full page, edit punch component||44 min|
|Full page, admin list component||2hr 6 min|
|Total Dev Time||4 hrs, 40 min|
|Total Time||7 hrs 10 min|
I’m pretty happy with the outcome of the screens. You can check out the visuals in the screens below