Compare commits

..

2 Commits

Author SHA1 Message Date
89e5e8a303 feat: add reporting pay type and logic
All checks were successful
Docker Build and Publish / build-and-push (push) Successful in 41s
2026-01-12 08:34:18 -05:00
9a939f0182 chore(frontend): update HTML title to Time Tracking Application 2026-01-12 08:34:18 -05:00
5 changed files with 35 additions and 1 deletions

View File

@@ -0,0 +1,19 @@
migrate((db) => {
const dao = new Dao(db)
const collection = dao.findCollectionByNameOrId("time_entries")
const typeField = collection.schema.getFieldByName("type")
// Add reporting_pay to the existing values
typeField.options.values = ["regular", "overtime", "standby", "callback", "non_contiguous", "reporting_pay"]
return dao.saveCollection(collection)
}, (db) => {
const dao = new Dao(db)
const collection = dao.findCollectionByNameOrId("time_entries")
const typeField = collection.schema.getFieldByName("type")
// Revert back to previous list
typeField.options.values = ["regular", "overtime", "standby", "callback", "non_contiguous"]
return dao.saveCollection(collection)
})

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>frontend</title>
<title>Time Tracking Application</title>
</head>
<body>
<div id="root"></div>

View File

@@ -152,7 +152,9 @@ const EntryForm = ({ onEntryAdded }) => {
<option value="regular">{t('type.regular')}</option>
<option value="standby">{t('type.standby')}</option>
<option value="callback">{t('type.callback')}</option>
<option value="callback">{t('type.callback')}</option>
<option value="non_contiguous">{t('type.non_contiguous')}</option>
<option value="reporting_pay">{t('type.reporting_pay')}</option>
</select>
</div>

View File

@@ -60,6 +60,15 @@ export const calculateBankedHours = (duration, type, dayType) => {
return Math.max(minPay, workedValue);
}
// --- REPORTING PAY ---
if (type === 'reporting_pay') {
// Article 9.03 (a): Minimum 4 hours pay at straight time rates
// OR time worked at applicable overtime rate, whichever is greater.
let workedValue = calculateOvertimeValue(hours, dayType);
const minPay = 4.0;
return Math.max(minPay, workedValue);
}
// --- REGULAR / OVERTIME ---
if (type === 'overtime' || type === 'regular') {
// "Regular" on a Time Tracker for Overtime usually implies "Regular Overtime" unless it is standard hours?

View File

@@ -37,7 +37,9 @@ export const translations = {
'type.regular': 'Regular',
'type.standby': 'Standby',
'type.callback': 'Call-back',
'type.callback': 'Call-back',
'type.non_contiguous': 'Non-Contiguous Hours',
'type.reporting_pay': 'Reporting Pay',
// Day Types
'day.workday': 'Normal Workday',
@@ -123,7 +125,9 @@ export const translations = {
'type.regular': 'Régulier',
'type.standby': 'Disponibilité',
'type.callback': 'Rappel au travail',
'type.callback': 'Rappel au travail',
'type.non_contiguous': 'Heures non contiguës',
'type.reporting_pay': 'Indemnité de rentrée',
// Day Types
'day.workday': 'Jour normal',