Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/dmaman86/shiftly/llms.txt

Use this file to discover all available pages before exploring further.

The Daily view is the primary data-entry surface in Shiftly. For a selected year and month it fetches the Hebrew calendar from the Hebcal API, generates one row per calendar day, and lets you record shift start/end times. Every time you save a shift the app recalculates that day’s pay breakdown and incrementally updates the running monthly total — no full recompute needed.
A base hourly rate must be entered in the Configuration panel before any monetary (₪) values appear in either the daily or monthly salary columns. Without a rate, the table still shows hours.

Work Table Layout

The work table renders every day of the selected month. Days are grouped into weekly bands separated by a bold bottom border on each Saturday (Shabbat). The table header adapts to the active display mode. Each row contains the following fixed left-hand columns, regardless of display mode:
ColumnWidthDescription
Day80 pxWeekday abbreviation + day-of-month number. Holiday/special-day chips (e.g. “Passover”, “Yom Kippur”) are shown inside this cell.
Sick48 pxCheckbox — marks the day as a sick day (WorkDayStatus.sick). Hidden on Shabbat / full-holiday days.
Vacation48 pxCheckbox — marks the day as a vacation day (WorkDayStatus.vacation). Hidden on Shabbat / full-holiday days.
Add shift (➕)48 pxIcon button that appends a new shift row for this day. Disabled when the day is marked sick or vacation.
In96 pxShift start time picker (or read-only display when saved).
Out96 pxShift end time picker (or read-only display when saved).
Controls120 pxCross-day checkbox, duty toggle (🚗), save (💾) / edit (✏️), and delete (🗑️) buttons.
The rightmost columns vary by display mode — see Display Modes below. A sticky footer row at the bottom of the table shows the running monthly totals in the same column layout as the per-day breakdown rows.

How to Add a Shift

1

Select year and month

Use the Configuration panel at the top of the Daily page to choose the correct year and month. The table regenerates with fresh calendar data from the Hebcal API.
2

Locate the day

Scroll to the date you want to enter. Each row shows the abbreviated weekday name and day number (e.g. Mo-14). Holiday chips appear on special days.
3

Click ➕ to add a shift

Press the add-shift icon button in the fourth column. A new ShiftRow is inserted with start and end time pickers initialised to midnight of that day.
4

Set start and end times

Click the In time picker and choose the shift start. Click the Out time picker and choose the shift end. If the end time falls on the next calendar day, check the cross-day checkbox (see Cross-Day Shifts).
5

Toggle duty shift (optional)

Click the 🚗 car icon to mark the shift as a duty shift. Duty status affects meal-allowance eligibility in per-diem calculations.
6

Save the shift

Click 💾 Save. The shift time inputs switch to read-only display and the pay breakdown columns update immediately. The monthly totals in the footer also refresh.
7

Edit or delete

Click ✏️ Edit to return a saved shift to edit mode. Click 🗑️ Delete to remove the shift entirely; the day’s contribution is subtracted from the monthly total.

Display Modes

The work table supports two display modes, toggled with the Full view switch in the table header. On mobile devices the table defaults to Compact mode; on desktop it defaults to Expanded mode.

Compact Mode

Compact mode shows a condensed view with three or four columns after the fixed left-hand columns:
ColumnDescription
Total HoursSum of all hours worked that day.
Regular HoursHours at 100% rate (up to the standard daily threshold).
Extra HoursOvertime hours above the standard daily threshold.
Daily Salary (optional)Gross pay for the day in ₪. Only shown when baseRate > 0.

Expanded Mode

Expanded mode shows a full breakdown across all pay categories:
Column GroupColumnDescription
Regular (שע״נ)100%Regular hours at standard rate.
125%First 2 overtime hours (next tier above standard).
150%Further overtime hours beyond the 125% tier.
Shabbat (שבת)150%Shabbat/holiday hours between 06:00–22:00.
200%Shabbat/holiday hours between 22:00–06:00.
Extras (תוספות)Shabbat EveShabbat-eve bonus 100% hours (extra100Shabbat).
20%Evening bonus hours (14:00–22:00).
50%Night bonus hours (22:00–06:00).
Absence (היעדרות)SickHours credited as sick-day pay.
VacationHours credited as vacation-day pay.
Per Diem (אש״ל)PointsPer-diem allowance points accrued for the day.
Meal Allowance (כלכלה)LargeLarge meal-allowance points.
SmallSmall meal-allowance points (shift C).
Daily SalaryComputed gross pay. Only shown when baseRate > 0.

Cross-Day Shifts

When a shift’s end time is typed or selected as earlier than its start time on the same calendar date, the cross-day checkbox in the Controls column begins blinking in amber and displays a warning tooltip. This indicates the system has detected a likely midnight-crossing shift.
  • Check the cross-day box to confirm the end time belongs to the following calendar day. The system marks end.date one day ahead and recalculates accordingly.
  • Do not check it if the time entry was simply a mistake — correct the end time instead.
  • Attempting to save a shift where end ≤ start without the cross-day box checked triggers a snackbar warning: “A shift crossing midnight was detected. Please check ‘cross day’ before saving.”
// ShiftRow.tsx — cross-day detection logic
const crossDay =
  dateService.getDaysDifference(localShift.end.date, localShift.start.date) > 0;

const hasError =
  !crossDay && endMinutes + (crossDay ? 1440 : 0) <= startMinutes;

Sick and Vacation Days

Marking a day as sick (WorkDayStatus.sick) or vacation (WorkDayStatus.vacation) has the following effects:
  • The sick and vacation checkboxes are mutually exclusive — checking one clears the other and resets shift entries for that day.
  • All shift input controls (add, edit, save) are disabled for the day; isEditable is false whenever status !== WorkDayStatus.normal.
  • The pay breakdown columns display the standard daily hours as hours100Sick or hours100Vacation in the expanded view.
Shabbat and full-holiday days (WorkDayType.SpecialFull) cannot be marked sick or vacation. The checkboxes are hidden via display: specialFullDay ? "none" : "inline-flex".

Day Types

Every WorkDayInfo carries a meta.typeDay value from the WorkDayType enum that drives which calculation path is used:
Enum ValueDescription
WorkDayType.RegularAn ordinary weekday or non-special Saturday. Uses standard regular + overtime rates.
WorkDayType.SpecialPartialStartA Friday or holiday eve. Regular rates apply until 17:00 (winter) / 18:00 (summer DST), then Shabbat rates (150%/200%) kick in.
WorkDayType.SpecialFullA full Shabbat or Jewish public holiday. Shabbat rates apply from the start; sick/vacation checkboxes are hidden.

Incremental Recalculation

Shiftly does not recompute the entire month on every keystroke. Instead the Redux store maintains a dailyPayMaps dictionary keyed by ISO date string. When a saved shift changes:
  1. The previous WorkDayMap for that date is subtracted from globalBreakdown via MonthPayMapReducer.subtract().
  2. The newly computed WorkDayMap is accumulated into globalBreakdown via MonthPayMapReducer.accumulate().
  3. The updated WorkDayMap is stored back into dailyPayMaps[dateKey].
If a day’s totalHours drops to zero (e.g. after deleting all shifts), removeDayPayMap is dispatched instead, cleanly removing the entry from the running total.
// DayRow.tsx — effect that drives incremental updates
useEffect(() => {
  const dateKey = workDay.meta.date;
  const prev = prevDayPayMapRef.current;

  if (dayPayMap.totalHours === 0) {
    if (prev) {
      removeDay(dateKey);
      prevDayPayMapRef.current = null;
    }
    return;
  }

  if (!prev || !isSameDayPayMap(prev, dayPayMap)) {
    addDay(dateKey, dayPayMap);
    prevDayPayMapRef.current = dayPayMap;
  }
}, [dayPayMap, workDay.meta.date, addDay, removeDay]);

Monthly View

See the aggregated monthly salary summary with per-diem and meal-allowance amounts resolved at historical rates.

Configuration

Set the year, month, standard hours, and hourly base rate that power all calculations.

Build docs developers (and LLMs) love