Set Time Calculator

kristianwood.github.io/set-calculator
Release Notes · April 3, 2026 · BETA V1.1.0
129
New Features
73
Bug Fixes
17
Improvements
51
Releases
💰
Finance Hub, Payroll Wrap & Cloud Sync
BETA V1.1.0 · Major Release · April 3, 2026
NewPayroll Wrap (PM Tools)
Complete your production payroll from within the app. Upload a budget document (Excel or CSV) to extract line numbers, or use the built-in ACCP standard lines. Add crew — they auto-import from submitted timesheets with hours and rate pre-filled. Enter hours and rate per person, and the app auto-calculates OT using ACCP rules (1.5× hrs 1-2, 2× hrs 3-4, 3× hr 5+). Add invoices and expenses as additional line items. Assign everything to budget line numbers. Export a clean Excel workbook with Summary (by line number) and Crew Detail sheets.
NewFull cloud sync for all finance data
Invoices, expenses, mileage, estimates, per diems, partial payments, payroll, and bank transactions all sync bidirectionally with Supabase. Data loads instantly from localStorage, then syncs from cloud in the background. Local-only records are pushed up automatically. Works across devices and domains (production + staging).
NewFinances — standalone page
Dedicated finances.html with its own CSS, JS, and layout. Faster loading, room to grow, shares auth with the main app.
NewExpense tracker with receipt capture
Full expense entry: date, pre-tax amount, HST/GST paid, 13 categories, production tagging, receipt photo capture with compression, recurring toggle, and notes.
NewMileage tracker (CRA $0.70/$0.64 per km)
Log drives with distance, route, purpose. Auto-calculates deduction based on YTD total. Creates expense records automatically.
NewHST/GST summary with quarterly breakdown
Collected vs paid (ITCs), net owing, Q1–Q4 breakdown ready for CRA filing.
NewP&L, cash flow, AR aging reports
Profit & Loss by category, monthly cash flow, and accounts receivable aging with color-coded overdue bands.
NewEstimates / Quotes → convert to invoice
Create quotes, track status (pending/accepted/declined), convert to real invoices with one tap.
NewPer diem, partial payments, invoice detail view
Per diem logging, partial payment tracking with progress bars, and full invoice detail sheets with line items and payment history.
NewBank CSV import with auto-matching
Upload CSV from RBC, TD, BMO, Scotiabank. Auto-detects format, matches deposits to invoices and withdrawals to expenses.
NewPayroll self-pay (salary/dividends)
Track payments through your corp with auto-calculated CPP, EI, and tax. YTD gross/net tracking.
NewRecurring expenses & T2125 tax export
Auto-generated monthly/yearly expenses. 5-sheet Excel: P&L, Invoices, Expenses, Mileage, Monthly Summary.
ImproveArchitecture: CSS split, service worker, toasts
CSS extracted to styles.css, offline caching via sw.js, all 39 alerts replaced with toasts, all confirms replaced with bottom sheets, logo compression, invoice counter synced to Supabase, Download My Data export.
SecurityRLS audit, subscription lockdown, CSP
All 7 Supabase tables verified. Subscription writes locked to service-role. Schedule crossoffs open-read removed. PM profile access scoped. Content Security Policy added. AD Tools opened to all crew, PM Tools gated to PM tier.
🧾
Create Invoice — Gear Rentals & Combined Packaging
BETA V1.0.3 · Feature Release · March 31, 2026
NewCreate Invoice — More → Finance → Create Invoice
Full invoice builder for gear rentals, labour, or both — available to all crew on the crew subscription. Users choose an invoice type on entry: Gear rental (PO #, Job #, Job Name), Labour (Job # and Job Name — no PO required), or Combined (two separate invoices packaged into one email).
NewAuto-incrementing invoice numbers
Invoice numbers (INV-0001, INV-0002, …) are generated automatically and increment each time an invoice is downloaded or emailed. The counter is saved to the account so it persists across sessions. Combined mode assigns two consecutive numbers — one for gear, one for labour. The field is read-only to prevent accidental edits.
NewInvoice Profile — Account → Invoice Profile
New section in Account settings where crew can set their name, company/trading name, address, email, phone, and HST/GST number once. This information auto-fills on every invoice created — no need to re-enter details each time. Users can also upload a company logo (PNG, JPG, or SVG) which appears at the top of all PDF invoices and in the preview. The profile syncs to Supabase and is shared with the existing labour invoice system.
NewDynamic line items with per-item tax control
Add unlimited line items — each with a description, quantity, rate, and auto-calculated amount. A dedicated Tax section lets users set the tax label (HST, GST, PST) and rate, then choose which specific items have tax applied via individual checkboxes. Tax labels and checkbox descriptions update live as line items are renamed or added.
NewUse Calculator for line items
A "Use Calculator for Line Item" button opens the full Set Time Calculator. After running a calculation, a green "Add to Invoice as Line Item" button appears in the results — tapping it adds the role name, hours worked, and total as a pre-filled line item on the invoice. This lets crew run their OT/penalty calcs and pipe the result directly into a gear or labour invoice.
NewCombined invoice — unified list with split-on-demand
The Combined mode builds one single invoice with all gear and labour items together. Each item has a Gear / Labour tag toggle — items from the calculator auto-tag as Labour, manual items default to Gear. The preview groups items by type under section headers. At any point — during preview or days later from My Invoices — you can tap "Split into Separate Invoices" to generate two new invoices (Gear + Labour) from the saved line items. The original combined invoice is replaced. This handles the common scenario where production pushes back on a combined invoice after it's already been sent.
NewDownload PDF & Email Invoice
The preview screen now has two separate action buttons: Download PDF (generates and saves the invoice as a formatted PDF) and Download PDF & Email Invoice (downloads the PDF and opens the mail app with the full invoice formatted in the email body — no blank email). Combined mode downloads two separate PDFs. The invoice counter only increments once regardless of which button is used first.
💚
Finances, Timesheet & Calendar
BETA V1.0.2 · Feature Release + Fixes · March 31, 2026
NewFinances hub — More → Finances
New personal finance screen with summary cards (Total Earned, Pending, Expenses, Net Income) scoped to any calendar year. Filter tabs: All, Paid, Pending, Invoiced, Expenses. Each entry shows production, role/category, date, colour-coded amount (+/−), and status pill. Year arrows switch between tax years instantly.
NewTax Package export (Excel .xlsx)
One-tap export generates a workbook with four sheets: Monthly Summary (invoiced / paid / expenses / net per month + year totals), Paid Invoices, All Invoices, and Expenses — formatted and ready for your accountant.
NewSubmit expense from calendar job
Crew can submit expenses directly from an existing calendar entry — an Expenses button appears in the edit sheet when editing a saved job. Opens the expense form pre-filled with the production name and job code. Hidden when adding a new job (no job code exists yet).
FixedTurnaround penalty was additive, not a replacement
ACCP: encroachment hours are paid at 3× instead of 1×, not in addition to the base day. The app was adding the full 3× penalty on top of the 10h minimum — paying 13 weighted hours for a 10h day with a 1h shortfall. Fixed to apply a net uplift of 2× per hour. A 1h turnaround shortfall on a 10h day now correctly yields 9h@1× + 1h@3× = 12 weighted hours = 53.92, not 25.08.
FixedTurnaround correction not flowing to timesheet
The TA-adjusted x1/x3 split and corrected total were only in the UI display layer. The timesheet was recomputing OT tiers from raw workedH on every preview/export. Fixed: getDays() now reads calcData.days[i].x1, .x3, and .total directly — TA corrections flow through to HTML preview, PDF, and XLSX.
FixedPrep / Wrap / Pre-light / Weather days hidden behind Hold toggle
A missing </div> on #jobHoldSection caused all other day-type toggles (Pre-light, Weather, Prep, Wrap) to be DOM children of the Hold section — they only appeared when Hold was on. Fixed with one closing tag.
FixedTimesheet column headers invisible (white on white)
HTML preview th was white text on dark — invisible on the white preview card. XLSX headers had no cell styles at all (aoa_to_sheet produces unstyled cells). Both now use dark #1C1C1E text on light grey #D1D1D6 readable on any background. PDF header fixed in the same pass.
FixedPDF column headers rendering with black background
doc.setFillColor(209,209,214) was called once outside the column loop. jsPDF bleeds the last fill colour into subsequent rect() calls — a preceding dark element was overwriting the grey. Fixed by moving all colour resets inside the per-cell loop.
FixedSyntax error from duplicate function declarations
Repeated patch sessions had multiplied expSubmit, invInit, and others 4× each — bloating the file from 626KB to 1.3MB and causing an Invalid or unexpected token runtime crash. Rebuilt from clean uploaded source applying only genuinely missing patches atomically via position-map replacement.
💰
Per-Job Expenses & Critical OT Fix
BETA V1.0.1 · Feature Release + Fix · March 26, 2026
NewPer-job expense submission for crew
Crew can now submit expenses directly from any job page via an Expenses accordion in the Job Documents section. Each submission captures: date, amount, category (Fuel/Mileage, Parking, Meals, Props, Equipment, Supplies, Travel, Other), description, and an optional receipt photo (JPG/PNG) or PDF up to 8MB. Expenses are tied to the job code and synced to Supabase in real time. The accordion shows a live pending-count badge when there are items awaiting PM approval.
NewPM expense approval dashboard
PMs see a live expenses summary tile on every job card in My Jobs — showing pending count, approved dollar total, and grand total at a glance. Tapping View & Approve Expenses opens a full-screen review sheet with four filter tabs (All / Pending / Approved / Rejected). Each expense card shows the amount, category pill, submitter name, date, receipt thumbnail, and one-tap Approve or Reject buttons. Approved totals update immediately and sync back to the My Jobs summary. PMs can also reset any decision back to Pending.
NewReceipt photo & PDF upload with full-screen viewer
When submitting an expense, crew can attach a receipt by tapping the upload zone — it accepts camera photos, gallery images, or PDF files. A thumbnail preview renders inline with a remove button. Both crew and PMs can tap any receipt thumbnail to view it full-screen. PDF receipts render with a red PDF badge. All receipt data is stored as base64 in the job_expenses Supabase table — no separate storage bucket required for typical usage.
FixedCritical: overtime calculated on elapsed time instead of hours worked
The multi-day calculator (calcDay()) was computing OT against elapsed clock time — call to wrap — rather than hours worked. This meant an unpaid 1-hour lunch was being counted toward the OT threshold. A standard 10-hour worked day (e.g. 7:30–18:30 with a 13:30–14:30 lunch) was incorrectly reporting 1 hour of OT and showing 11.5 billable hours instead of 10. The fix removes the elapsedH variable entirely and calculates OT from workedH — which already has the unpaid lunch deducted — matching ACCP guidelines: "overtime pay for time worked beyond the daily minimum hours." Meal penalty OT tier boundaries were also updated to shift by the lunch gap so tier thresholds remain aligned with the corrected worked-hours clock.
FixedSix broken JS string quote escapes in expense render functions
Inline onclick handlers built inside JS template strings were using '' (two single quotes) as an escape sequence, which actually terminated the surrounding string literal and broke the parser. Affected calls: expOpenPMView(), expViewStoredReceipt() (×2), and expUpdateStatus() (×3). All six were corrected to use proper \' escaping, resolving the Uncaught SyntaxError: Unexpected string console error.
👤
Dedicated Account Page & Emergency Contact Fix
Alpha V1.3.9.2 · Improvement · March 24, 2026
ImprovedAccount is now a full dedicated screen
Account has moved from an inline section buried inside the More screen to its own proper full-page view. Tap the Account row in More — which now shows your name and email — to open it. The screen is organised into three clear sections: My Roles, Emergency Contact, and Preferences (Dark Mode, New Calculation, Sign Out).
ImprovedMore screen is now a clean navigation hub
The More screen previously dumped an inline role picker, settings toggles, and account actions all on one page. It's now a proper list of tappable rows — Account, Finance (My Invoices), and PM Tools — matching the navigation pattern of every other screen in the app.
ImprovedEmergency Contact PM-only note always visible
The privacy disclaimer — "Visible to your PM only. This information is never shown publicly or to other crew members — only the Production Manager of a job you're on can see your emergency contact." — now sits directly and permanently beneath the Emergency Contact card on the Account page. It was previously easy to miss. The note uses the same accent-colour info style as other system notices.
🆘
Emergency Contacts & PM Crew Tab
Alpha V1.3.9.1 · Feature · March 24, 2026
NewEmergency contact per account
Every crew member can now add an emergency contact (full name, phone number, relationship) during onboarding — presented as a dedicated step after role selection — or anytime from their Account screen. Stored as emergency_contact JSON on their Supabase profiles row. Fills in once and syncs across devices automatically.
NewPM-only visibility — never public
Emergency contact data is only readable by the PM of a job the crew member is on. It is never shown publicly, never shown to other crew members, and not included in any exported documents. A clear info note on both the onboarding step and the Account screen states this explicitly so crew always know who can see their information.
New👥 Crew tab on every PM job card
Each job card in My Jobs now has a "👥 Crew" button alongside Preview, Edit, and Share. Tapping it opens a bottom sheet listing every crew member who has added that job to their calendar, showing their name, role, and emergency contact (name, relationship, phone). The PM is the only person who sees this view.
NewHold / Booked status per crew member
In the Crew sheet, the PM can toggle each person between Hold (grey) and Booked (green) with a single tap. Status is saved to a new crew_job_status Supabase table (keyed on job_code + crew_user_id) and persists across sessions. Crew can also change their own status from the Jobs tab on their end.
NewSupabase schema additions
Two schema changes required: alter table profiles add column emergency_contact jsonb stores the crew member's emergency contact on their profile. A new crew_job_status table (job_code, crew_user_id, pm_user_id, status) with row-level security stores Hold/Booked per crew per job — PM can read/write all rows for their jobs, crew can read their own row.
🚨
Critical Hotfix — App Broken After V1.3.8.5
Alpha V1.3.8.6 · Hotfix · March 22, 2026
FixedEntire app non-interactive after V1.3.8.5 deploy
A str_replace during the per-day copy button addition used function showInvoice(){ as a boundary marker in the old string but omitted it from the replacement. This silently deleted the function declaration, leaving its body as orphaned loose statements. JavaScript failed to parse the entire script block — all functions were undefined and every button was unresponsive. Fixed by restoring the missing declaration.
📋
Per-Day Copy + Invoice & Meal Penalty Fixes
Alpha V1.3.8.5 · Feature + Fixes · March 22, 2026
NewPer-day copy button on every day result card
Each day result card in a multi-day shoot now has a "Copy Day N for invoice" button at the bottom. Tapping it copies a fully formatted breakdown for that day — role, rate, call/wrap, lunch, all OT rows, turnaround penalty, meal penalties, and a DAY N TOTAL line. The button turns green and shows "✓ Copied!" for 2.5 seconds.
FixedInvoice TOTAL row showed wrong hours
The TOTAL row in the copied invoice breakdown showed billWorked (actual hours, e.g. 13.5h) while the header showed invoiceHrs (weighted equivalent, e.g. 16h). Fixed — both now show invoiceHrs consistently.
New30-minute lunch minimum enforced (ACCP)
If lunch is under 30 minutes: shortfall added back as worked time, 2× short-lunch penalty fires for the shortfall, and the second meal deadline clock starts from lunchOut + 30min rather than the actual early return time. A standard 30-min lunch is unaffected.
🔧
Logo, Splash & What's New Fixes
Alpha V1.3.8.3–V1.3.8.4 · Patches · March 22, 2026
FixedSplash screen logo clipped at top (V1.3.8.4)
The icon SVG was using a transform="translate(-190,-40)" offset to re-origin design sheet coordinates. Clip paths apply before transforms so they were misaligned — the clapper arm was cut off at the top and the squircle clip wasn't applied. Rewrote the SVG with native 0 0 300 300 coordinates and a wrapping <g clip-path="url(#sq)">.
FixedSplash buttons not visible — stray closing div (V1.3.8.4)
A stray </div> was closing #splash prematurely after the logo and title only, leaving Get Started, What's New, and Add to Home Screen outside the screen container and invisible.
NewWhat's New — V1.3.8.0 branding entry + dark card style (V1.3.8.3)
The What's New sheet now opens with a dark navy "New Icon & PWA Branding" card styled with the icon's #12082A background and a "Major Update" badge. The renderer was updated to support dark-background featured entries. Dark Mode entry corrected to V1.3.7.1.
🎬
New Icon & PWA Branding
Major Update
Alpha V1.3.8.0 · March 22, 2026
NewRefined app icon — clapper + document + clock
The splash screen logo has been replaced with a fully redesigned icon. The new design features a deep navy squircle (#12082A) containing a white document with folded corner, a striped purple clapper arm and body, a separation line with hinge dots, document content lines, and a purple clock in the bottom-right. All elements are crisp at every size from 20pt to 1024pt.
NewiOS home screen icon — apple-touch-icon.png (180×180)
A new 180×180 PNG is generated from the master icon at exact iOS proportions. This is the image iOS uses when someone taps "Add to Home Screen" — it appears on their home screen grid with rounded corners applied automatically by the OS.
NewAndroid / manifest icons — 192×192 and 512×512
Updated icon-192.png and icon-512.png with the new design. The 512px version is used by Android for high-resolution displays and splash screens. Both are tagged maskable in the manifest so Android can apply its adaptive icon shape.
NewBrowser favicon — favicon-32x32.png
A new 32×32 PNG favicon matches the new icon. Previously the favicon was a completely different inline SVG design — now all contexts (browser tab, bookmarks bar, home screen, manifest) show the same consistent icon.
NewInline SVG favicon updated to match new design
The <link rel="icon"> inline SVG in <head> has been redrawn to match the new icon: dark navy squircle, document with folded corner, striped clapper, and clock. This renders in browsers that support SVG favicons (Chrome, Firefox, Edge) at any resolution without pixelation.
NewTheme colour updated — #12082A across all surfaces
The PWA theme colour has been changed from the old mid-grey #2d2d45 to the icon's deep navy #12082A. Updated in: <meta name="theme-color"> (browser chrome on Android), manifest.json theme_color (Android splash), and manifest.json background_color (Android splash background). The result is a seamless dark launch experience — no flash of grey.
NewApp name updated to "Set Calculator" everywhere
apple-mobile-web-app-title changed from "Set Calc" to "Set Calculator" — this is the label that appears under the icon on an iOS home screen. The manifest short_name is also updated to match.
NewSplash screen logo CSS refined for square icon
The .splash-svg CSS was updated for the new square icon proportions: width: min(160px, 44vw), border-radius: 36px, and a deeper drop shadow matching the dark squircle (rgba(18,8,42,0.45)). The floating animation is unchanged.
NewCanvas-generated PNGs — pixel-perfect at all sizes
All four PNG files are generated programmatically using the browser Canvas API with the exact same drawing code used for the SVG icon. Each size is drawn at its native resolution (not downscaled from a photo) — so the 32px favicon and 512px icon are equally crisp. The squircle clip path, stripe opacity, and clock hands are all mathematically scaled.
📤
Timesheet Submission — Crew → PM → Accounting
Alpha V1.3.7.5 · Feature Release · March 22, 2026
NewSupabase submitted_timesheets table
A new table stores crew timesheet submissions linked to a job code. Schema: id (UUID PK), job_code (FK → posted_jobs), crew_user_id (FK → auth.users), crew_name, crew_role, sheet_data (full timesheet JSON), total_pay, submitted_at. A unique index on (job_code, crew_user_id) means re-submitting overwrites the previous version. RLS: crew read/write own rows; PMs read all rows for jobs they own.
New"Submit Timesheet to PM" button on timesheet page
When a crew member navigates to the timesheet page from a job (via the Jobs tab or calendar), a green "Submit Timesheet — [Job Name]" button appears below the Export PDF/Excel buttons. Tapping it sends the full sheet data, total pay, crew name, and role to Supabase. If the crew member submits again, it upserts — updating rather than duplicating. The button shows "✓ Submitted to PM" on success with a status message.
NewJob context passed from calculator to timesheet
saveToSession() in index.html now also writes activeCalcJob to sessionStorage when the calculator was launched from a calendar job. This carries jobCode, jobId, and prod into the timesheet page so the Submit button knows which job to link the submission to.
NewTimesheet count badge on My Jobs cards
Each job card in My Jobs now shows a green badge (e.g. "3 timesheets") when crew have submitted. The count loads from Supabase when mjInit() runs — a single query fetches all submission counts for all the PM's jobs at once.
New"Send to Accounting" button on My Jobs cards
When a job has at least one submitted timesheet, a "Send to Accounting" button appears inline on the job card. Tapping it fetches all submissions from Supabase and composes a detailed mailto — one entry per crew member showing their name, role, rate, total pay, and a day-by-day breakdown. The email also includes the grand total payroll figure. The accounting address, subject, and body are all pre-filled.
New"Add Email" prompt when accounting email is missing
If a job has submitted timesheets but no accounting email is set, an amber warning and "Add Email" button appear instead of "Send to Accounting". Tapping opens the Edit modal directly so the PM can add the email and then send.
💰
Accounting Integration — Email & Timesheet Submission
Alpha V1.3.7.4 · Feature Release · March 22, 2026
NewAccounting email field in Claim a Job
A dedicated "Accounting" section (Section 4.5) sits between Shoot Information and Documents in the Claim a Job form. The accounting email auto-fills from the selected production company's stored email, but is independently editable per job. Saved as job.accountingEmail and pushed to Supabase with all other job data.
NewAccounting email in My Jobs Edit modal
The Edit modal now includes an Accounting email field. On open, it pre-fills from the saved job's accountingEmail, falling back to the company's stored email. Saved on "Save Changes" and synced to Supabase.
NewAuto-fill from production company
When a PM selects a production company from the dropdown, the accounting email field auto-fills with that company's stored email (if the field is empty). When a new company is saved via "New Company", the accounting email field also auto-fills immediately.
NewPM — "Send to Accounting" button on job preview
When a PM views their job preview and an accounting email is set, a green "Send to Accounting" button replaces the Add to Calendar CTA (PMs don't add their own jobs to their calendar). Tapping it opens a pre-composed email with the full job summary: production name, company, job number, shoot date, location, cameras, status, and all department notes formatted by role. The accounting address, subject, and body are all pre-filled.
NewCrew — "Submit Timesheet to Accounting" button
When crew view a job that has an accounting email set, a "Submit Timesheet to Accounting" button appears on the job preview. Tapping it opens a pre-composed mailto with a professional submission message pre-filled: production name, company, job #, and shoot date. The crew member attaches their downloaded timesheet PDF and sends. No backend required — uses the device's native mail app.
NewDepartment Notes included in accounting summary
The PM's "Send to Accounting" email includes all department notes from the job, formatted by role label (e.g. [Camera] ..., [G&E / Lighting] ...). Accounting gets a complete picture of all role-specific instructions in one email.
📋
Department Notes — Role-Targeted Job Briefs
Alpha V1.3.7.3 · Feature Release · March 21, 2026
NewDepartment Notes section in Claim a Job
A new "Department Notes" section sits between Role Visibility and Crew Access in the Claim a Job form. PMs can add any number of notes (up to 10), each assigned to specific roles. Each note has its own role-pill selector grouped by department (Camera, G&E, Sound, Styling, Transport, Production/Art/Locations) and a free-text area. Notes are saved as a deptNotes array on the job object and pushed to Supabase alongside all other job data.
NewDepartment Notes in My Jobs Edit modal
The same Department Notes UI is available in the Edit modal. When a PM opens an existing job to edit, any previously saved department notes pre-load with their role assignments and text. Adding, removing, or editing notes re-saves to Supabase on "Save Changes".
NewRole-filtered Department Notes in Job Preview
Crew see a "Department Notes" collapsible section on the Job Preview screen. Notes are filtered to only show entries where the crew member's saved roles match the note's assigned roles. Notes with no role restriction are visible to everyone. PMs see all notes with the role assignment label displayed above each entry. Tapping "Show all" (from the role banner) also reveals all department notes.
NewShared renderDeptNotesList() renderer
A single renderDeptNotesList(containerId, notesArr, prefix, ...) function drives both the Claim a Job form and the Edit modal. It accepts the target container and array by reference so both forms share identical UI logic with no duplication.
🔧
What's New — Cache Bust + Dark Mode Fix
Alpha V1.3.7.2 · Patch · March 20, 2026
FixedWhat's New sheet showing stale content after deploy
The sheet cached content with a boolean body.dataset.built = '1' that never cleared — so after every new deploy, the old content was silently shown. Fixed by switching to body.dataset.builtVersion = 'V1.3.7.2'. The sheet now rebuilds whenever the stored version doesn't match the current app version. Each deploy automatically shows fresh content.
New"Full notes ↗" link added to What's New header
The What's New sheet header now has a "Full notes ↗" button alongside the × close. Tapping it opens release-notes-march-18-2026.html in a new tab for the full detailed release history.
FixedWhat's New sheet ignoring dark mode
The sheet background and header were hardcoded to #f2f2f7 and #1c1c1e. Changed to var(--surface-card) and var(--text). Tag pill colours in buildWhatsNewHTML() now have dark-mode variants. applyDarkMode() also clears the built-version cache so the sheet rebuilds with correct colours on next open.
🌙
Dark Mode
Alpha V1.3.7.1 · Feature Release · March 20, 2026
NewFull dark mode — toggle in Account & More
A Dark Mode toggle (moon icon) is now available in both the Account screen and the More screen. Toggling it instantly applies a dark theme across the entire app with a smooth 0.3s transition.
NewComplete [data-theme="dark"] CSS variable system
Implemented via a data-theme="dark" attribute on <html>. All CSS variables flip: backgrounds go to near-black #0f0f10, glass surfaces use dark semi-transparent fills, text inverts to #f2f2f7, accents brighten for contrast. Every surface is covered — calculator, calendar, role picker, job preview, modals, sheets, nav bar, inputs, and turnaround cards.
NewSaved per account — Supabase profiles.dark_mode
A new dark_mode boolean column on the profiles table persists the preference across devices. On login it loads from Supabase; on toggle it saves immediately. Before auth resolves, the setting loads from localStorage so there's no flash of light mode.
NewExports unaffected — pure UI change
PDF timesheets and Excel exports use hardcoded JavaScript colour values and never read CSS variables or DOM styles. Dark mode has zero effect on any exported file.
FixedHardcoded surface colours replaced with CSS variables
Hardcoded colours like #f2f2f7 and #e4e4ea in CSS classes (.cal-confirm-sheet, .save-sheet, .install-steps, calendar header) are now replaced with new --surface-card, --surface-bg, and --nav-bg variables so every surface flips correctly.
🎭
Role Profiles — Personalized Experience End-to-End
Alpha V1.3.7.0 · Feature Release · March 20, 2026
NewOnboarding — role selection on first launch
First-time users who tap Get Started are now shown a full-screen role selection screen before reaching the calculator. All 30 ACCP roles are shown as pill checkboxes grouped by department. A "Continue →" button saves and proceeds to the filtered role picker. A "Skip for now" option goes straight to the full picker. Returning users with saved roles bypass onboarding entirely and go straight to their filtered picker.
NewSupabase profiles table — cross-device role sync
A new profiles table (id UUID → auth.users, roles text[]) stores each user's selected roles. Row-level security ensures users can only access their own row. On every login, roles are loaded from Supabase and cached in localStorage. Any change to roles is immediately upserted to Supabase — so switching devices picks up where you left off.
NewMy Roles in Account screen
The Account screen has a new "My Roles" section showing all 30 roles as pill checkboxes grouped by department. Tapping any role toggles it and auto-saves to Supabase. A summary line shows the count ("3 roles selected") with a "Clear all" option. The role picker updates live as you change selections.
FixedMy Roles not showing in More page
The More screen's more-roles-list container existed but was never populated — populateMore() wasn't calling renderRoleCheckboxes() with the right target. Fixed. Additionally, toggleUserRole() and clearUserRoles() now refresh all three role containers simultaneously (Account, More, Onboarding) so they're always in sync without requiring a navigation round-trip.
NewSmart role picker — filtered to your saved roles
When you have saved roles, the role picker shows only those roles with a "Showing your saved roles" banner. A "View all roles →" button at the bottom opens the full list with blue dots on your saved roles. "← Show my roles" collapses back. Production Manager, AD, 2nd AD, and Production Coordinator always see the full list regardless of selection. No saved roles = full list (backwards compatible).
NewPM job role targeting — Claim a Job
A new "Role Visibility" section in Claim a Job lets PMs choose which roles see the job. All 30 roles are shown as toggleable pills. Empty selection means all roles can see it. A "Select all" shortcut is available. The chosen targetRoles array is saved with the job and pushed to Supabase alongside all other job data.
NewPM job role targeting — My Jobs Edit modal
The Edit modal has the same Role Visibility section. When a PM opens the edit modal, existing targetRoles are pre-loaded into the pill UI. Saving updates the job locally and re-upserts to Supabase so crew see the change within 30 seconds.
NewRole-filtered Job Preview for crew
When a crew member views a job, the preview detects their saved roles and compares them against the job's targetRoles. If there's a match, a blue banner shows "Showing info for: Assistant Camera" with a "Show all" button. Tapping "Show all" reveals the full job details with a green "Showing all job information" banner and a "Show my info" button to return to the filtered view. PMs always see the full view plus a role targeting summary below the job code.
NewRole match badge on Jobs tab cards
Each job card in the crew Jobs tab now shows a role badge in the top-right corner. If the job is targeted at your role, a purple badge shows your matched role (e.g. "Assistant Camera"). If the job targets roles that don't match yours, an amber "All roles" badge appears with a note to View Details for full info. Untargeted jobs show no badge.
NewALL_ROLES — single source of truth
All 30 ACCP roles are now defined in a single ALL_ROLES constant with name, rate, minHrs, type, group, and prepWrapRate. This drives the role picker, account checkboxes, onboarding, PM role targeting, and crew filtering. Previously role data was duplicated in three separate places.
🎭
Role Profiles — Personalized Role Picker
Alpha V1.3.7.0 · Feature Release · March 19, 2026
NewSupabase profiles table
A new profiles table stores each user's selected roles as a text array. Row-level security ensures users can only read and write their own profile. Roles sync across devices — selecting Assistant Camera on your phone shows it pre-selected on your iPad.
NewAccount screen — My Roles section
The Account screen now has a "My Roles" section showing all 30 ACCP roles as pill-style checkboxes, grouped by department (Camera, G&E / Lighting, Sound, Styling & Make Up, Transport & Craft, Production / Art / Locations). Tap any role to toggle it. Changes auto-save to Supabase immediately. A summary at the bottom shows how many roles are selected with a "Clear all" option.
NewRole picker — filtered to your saved roles
When you have saved roles, the role picker shows only those roles with a "Showing your saved roles" banner. This removes the clutter of all 30 roles and puts your typical roles front and centre.
New"View all roles" toggle
A "View all roles →" button at the bottom of the filtered picker opens the full list. In all-roles mode, a blue dot marks your saved roles so they're easy to spot. "← Show my roles" returns to the filtered view. Only appears when you have saved roles.
NewProduction Manager — always sees all roles
If your saved roles include Production Manager, Assistant Director, 2nd Assistant Director, or Production Coordinator, you always see the full role list regardless of other selections. The Account screen shows "✓ Production Manager — all roles always visible" instead of a count.
NewALL_ROLES master constant
All 30 ACCP roles are now defined once in a single ALL_ROLES array with name, rate, minHrs, type, group, and prepWrapRate. This is the single source of truth used by the role picker, the calculator dropdown, and getDays(). Previously role data was duplicated across three separate places in the code.
FixedAccount screen now auto-populates when navigating to it
showScreen('account') now automatically calls populateAccount(), which renders the user's email, name, and role checkboxes. Previously the account screen required a separate manual call to populate.
🔓
PM Tools — Password Wall Removed
Alpha V1.3.6.4 · Patch · March 19, 2026
FixedClaim a Job and My Jobs no longer require a password
The "PM Access" password modal has been removed. Claim a Job and My Jobs are now directly accessible from the More tab and My Jobs header. The modal HTML, claimJobAuth(), claimJobCloseModal(), and claimJobSubmit() functions are all removed. Access control will be handled by account-level role permissions in a future update.
🔄
Turnaround Penalty — Calculator & Timesheet
Alpha V1.3.6.3 · Patch · March 19, 2026
NewTurnaround penalty shown as 3× row in day breakdown
When a turnaround shortfall exists (less than 10h rest between days), the affected day's breakdown now shows a red "Turnaround penalty 3×" line item — e.g. 1h shortfall × $213.48/hr = $213.48. The Day total and Grand total both include the penalty. Previously the penalty was only shown in the turnaround card between days, not inside the affected day's breakdown.
FixedTimesheet columns not reflecting turnaround shortfall
The turnaround shortfall was being applied at the display layer in buildTSHtml but not at the data layer in getDays(). Since PDF export and Excel use the raw day data from getDays(), they were unaffected. Fixed by applying the shortfall in getDays() itself — subtracting shortfall hours from x1 and adding them to x3 before the data is passed anywhere. For 1h shortfall on Day 2: x1 = 9.00h, x3 = 1.00h, Total Pay Hrs = 12.00, Total $ = $853.92.
FixedGrand total now includes all turnaround penalties
The grand total bar for multi-day shoots now sums turnaround penalties alongside all day totals. For the sample (Day 1 = $1,209.72, Day 2 with 1h TA penalty = $853.92), grand total = $2,063.64.
🔧
Jobs Tab — Add to Calendar + Fetch Fix
Alpha V1.3.6.1 – V1.3.6.2 · Patches · March 19, 2026
FixedAdd to Calendar not working from Jobs tab
crewJobsAddToCal(code) looked up the job in the in-memory _crewJobsData array, which is only populated after the Jobs tab has loaded and synced from Supabase. If the crew member hadn't opened the tab yet, the array was empty and the function silently did nothing. Fixed by making the function async — if the job isn't in memory, it fetches it directly from posted_jobs in Supabase before proceeding.
FixedView Details also falls back to Supabase fetch
Same fix applied to crewJobsViewFull(code) — if the job isn't in the in-memory cache, it fetches from Supabase before opening the Job Preview screen.
FixedCalendar entry ID undefined for Supabase-fetched jobs
Jobs fetched from Supabase don't have a local id field, so calendar entry IDs were generating as cj_undefined_timestamp. Changed to job.id || job.jobCode || Date.now() for a reliable unique ID.
FixedTurnaround timesheet: shortfall applied too late
Earlier attempt applied the turnaround shortfall only in buildTSHtml (display layer). The proper fix moves it to getDays() so the adjusted x1/x3 values flow through to PDF, HTML preview, and Excel consistently.
💼
Crew Jobs — Live Job Board
Alpha V1.3.6.0 · Feature Release · March 19, 2026
NewJobs tab added to navigation bar
A new "Jobs" tab (briefcase icon) sits between Calendar and More in the bottom nav. Crew can see all their active productions in one place and get live updates from the PM any time the job is edited.
NewSupabase posted_jobs table
A new Supabase table backs the crew jobs feature. PMs write to it when they create or edit a job; crew read from it. Row-level security ensures any authenticated user can read all posted jobs, but only the PM who created a job can update or delete it.
NewAdd job by code
Crew enter a job code (e.g. ACMEAUT-2026-042) to subscribe to a job. The code is looked up in Supabase in real-time — if found, it's added to the crew member's personal job list. The code is stored locally so the crew member never has to enter it again.
NewLive sync — 30s polling
The Jobs screen polls Supabase every 30 seconds when open, and on every manual refresh (↺ button). When a PM edits a job — changes the shoot date, location, camera count, or crew notes — all crew members see the update within 30 seconds of opening the tab.
NewCrew notes from PM visible on job card
If the PM has entered crew-facing notes (via My Jobs → Edit), they appear in a highlighted section on the crew's job card. PM internal notes stay private. Crew notes update live alongside all other job data.
NewView Details + Add to Calendar from crew card
Each job card has a "View Details" button that opens the full Job Preview screen (weather, map, call sheet, schedule), and an "Add to Cal" button that adds the shoot days as a Hold to the crew member's personal calendar.
NewPM create/edit syncs to Supabase automatically
When a PM creates a job via "Create Job" or saves edits via My Jobs → Edit, the job is immediately upserted to posted_jobs in Supabase. No manual publish step needed — the job goes live for crew the moment it's saved.
🔧
What's New Panel + Visibility + Toggle Fix
Alpha V1.3.5.9 – V1.3.5.11 · Patches · March 19, 2026
FixedWhat's New clearing nav bar on open
openWhatsNew() was calling nav.classList.remove('visible') to hide the nav — but the close function sometimes failed to restore it, leaving the nav permanently hidden. Removed the hide/show entirely since the sheet is z-index: 1100 which naturally covers the nav at z-index: 1000. Also moved #whatsNewSheet and its overlay to direct children of <body> via DOMContentLoaded to prevent transform containment issues.
FixedMy Jobs Edit modal — hard to read text
The inner card used var(--glass) = rgba(255,255,255,0.52) — semi-transparent over a dark blurred backdrop, making labels nearly invisible. Changed to solid #f2f2f7 with targeted CSS overrides for label colour (#636366) and input background (rgba(255,255,255,0.85)).
Fixed"Dinner at camera wrap" toggle description corrected
The subtitle previously said "ON = dinner served at cam wrap (late penalty applies)" — which was wrong. ACCP rules say if dinner is served before or at camera wrap, no penalty applies. Updated to: "ON = dinner served before or at camera wrap (no penalty applies). OFF = no dinner provided (penalty runs to your wrap)."
NewWhat's New panel — full screen with close button
The What's New panel is now full-screen (position:fixed; inset:0) with a sticky header containing a circular × close button. Previously a bottom sheet capped at 90vh with no close button visible on desktop.
NewRelease notes counters updated to accurate totals
Counters were stale at 26 New / 11 Improvements / 10 Fixes. Recounted every tag-new, tag-fix, and tag-improve tag in the document. Added a 4th "Releases" counter showing 17 distinct versions shipped.
🧭
Navigation
Bottom tab bar
NewBottom navigation bar
Frosted glass tab bar with Calculator, Calendar, and Account tabs. Appears on all main screens including the Get Started splash screen. Active tab highlights in purple. Hides automatically when bottom sheets open.
NewAccount screen
Shows your email address, a New Calculation shortcut, and a Sign Out button with confirmation prompt.
ImprovedNav bar visible on splash
The bottom navigation bar now appears on the Get Started screen, giving access to the Calendar and Account tabs even before starting a calculation.
FixedSheets no longer blocked by nav bar
Sheet z-index raised above the nav bar (1100 vs 1000). Nav bar also hides when any sheet opens and reappears when it closes. Cancel/Save buttons now always reachable above the home indicator.
📅
Calendar
WeekCal-style month view
NewMini month grid with inline job bars
Full WeekCal-style calendar grid. Multi-day jobs render as continuous colour bars spanning across days. The job title is centred over its span on every row — no more truncation on week breaks. Up to 3 job lanes per row with overflow indicator.
NewAdd / Edit Shoot sheet
Bottom sheet with production name, start/end dates, role dropdown (all ACCP roles with auto-filled day rates), pay, 10 colour swatches, and notes. Role selection auto-fills the day rate field.
NewSub-event day types
Four special day types per job: Pre-Light (amber→job colour, single dates), Weather Hold (blue, single dates), Prep (purple→job colour, date range), and Wrap (job colour→green, date range). Each renders as a gradient-blended bar. Sub-event dates automatically extend the job's overall start/end span.
NewCalculate from calendar job
Tap Calc on any job card to launch the calculator pre-loaded with that job's shoot days. Saves results back to the card — shows a 📅 Saved badge and updates the stored pay total automatically.
NewShare job
Share a full job (all details + saved calc data) or just the hours summary as a URL. Uses native share sheet on iOS and clipboard fallback on desktop. Recipients can import directly into their own calendar.
NewDelete with confirmation
Tapping the trash icon shows a confirmation sheet naming the production before deleting. Removes from localStorage and Supabase simultaneously.
ImprovedPast events auto-grey
Jobs whose end date has passed render with grayscale + reduced opacity so current and future work stays visually prominent.
NewDelete from the Edit Shoot sheet
When editing a job, a red Delete button now appears in the action bar between Cancel and Save. Tapping it closes the edit sheet and opens the same confirmation prompt used by the trash icon on job cards — so there's no way to accidentally delete without confirming. The button only appears in edit mode; it's hidden when adding a new shoot.
💰
Monthly Income Summary
Alpha V1.3.2.1 · New this release
NewProjected monthly income box
A frosted glass summary card sits between the calendar grid and the day detail cards. Shows three figures for the current month: Actual (green — days that have already passed), Projected (purple — future days still to come), and Total. Includes day and job count subtitles. The title updates with the month name as you navigate — "March 2026 Income", "April 2026 Income", etc.
NewPrecise calc data used when available
If you've run the calculator for a job and saved the results, the income box uses the exact daily totals from those calculations (including overtime and meal penalties). For jobs without saved calc data it falls back to dividing the stored day rate evenly across the job's shoot days.
NewMonth-boundary-aware
For jobs that span multiple months (e.g. a 3-week shoot crossing March into April), only the days that fall within the currently displayed month are counted. Navigate to April and the same job contributes only its April days.
☁️
Cross-Device Sync
Supabase · Offline-first
NewCalendar jobs sync to your account
Calendar events are now saved to Supabase under your account. Add a shoot on your iPhone and it appears on your iPad or any other device you're logged into — no manual export needed. A "Syncing…" / "✓ Synced" indicator appears in the calendar header during each sync.
NewOffline-first with cloud merge
LocalStorage still works as a cache so the calendar loads instantly. On each session the app merges local and remote jobs — remote wins for the same job ID. Any local-only jobs (created while offline) are pushed up on reconnect.
FixedSync was silently failing
The Supabase client was stored as _sb but all sync functions were checking for window._sb — always undefined — so every sync call bailed out immediately without an error. Fixed by correcting all variable references. Jobs now correctly upsert and delete from the cloud.
Calculator
Shoot day billing
NewPrep & wrap day toggle
Per-day toggle in each day panel. Prep/Wrap type buttons auto-set based on day position. Auto-fills the flat 10H rate from the role's prep/wrap rate (e.g. Stylist $751, Asst Stylist/MU $502). No OT or meal penalties on prep/wrap days. Result card shows a purple "prep" or green "wrap" badge.
NewSave to Calendar job
When the calculator is launched from a calendar job, a "Save to Job" button appears in the results. Tapping it writes the per-day totals back to the job's calcData, updates the stored pay figure, and syncs to the cloud.
ImprovedTurnaround tracking
Turnaround shortfall and penalty data now flows through all three sheet-building paths (liveUpdatePreview, generateSingle, generateBatch) and into the final timesheet HTML. MP/turnaround notes section appears in both PDF and Excel exports.
📄
Timesheet
PDF & Excel export
NewExport to Excel
Full timesheet export to .xlsx via SheetJS (loaded on demand). Includes all days, hours, OT splits, meal penalties, and turnaround notes. Matching column layout to the PDF export.
NewMP/turnaround notes in exports
Meal penalty alerts and turnaround shortfall info now appear as a dedicated notes section in both PDF and Excel exports.
ImprovedPrivacy notice on sensitive fields
SIN # and HST/GST fields display a privacy notice reminding users not to share timesheets containing these fields unless necessary.
App & Polish
PWA, safe area, accessibility
NewProgressive Web App (PWA)
App is installable on iOS and Android via Add to Home Screen. Includes manifest.json, 192px and 512px icons, and Apple touch icon. Splash screen Add to Home Screen button triggers the browser prompt directly.
NewWhat's New sheet
Scrollable bottom sheet accessible from the splash screen summarising all changes by category. Version shown in the header. Scrolls independently of the page.
ImprovedSpecial thanks credit
Splash screen credits Dylan Pouliot, Warren Milando & Al Kuipers below the copyright line.
FixedSafe area padding across all screens
Calendar header, role picker, invoice, account, and add-shoot sheet all respect env(safe-area-inset-top) and env(safe-area-inset-bottom). Back buttons and action buttons no longer hide behind the Dynamic Island or home indicator on any iPhone.
FixedAdd Shoot button overlapping nav bar
Floating Add Shoot button repositioned 72px above window bottom (above the nav bar). Calendar screen has 130px bottom padding so job detail cards scroll fully clear of the button.
FixedCalendar bar labels truncating
Labels now show on the first cell of every row the job spans, centred over that row's visible portion. Bar shapes also fixed to round correctly at week breaks.
FixedGet Started screen unresponsive
A literal newline inside a JS string was crashing the entire script block on load. Fixed by escaping as \n. All code now passes Node.js syntax validation.
🗑️
Delete from Edit Sheet
Alpha V1.3.2.1 · Patch
NewDelete button in Edit Shoot sheet
When you open a job to edit it, a red Delete button now appears alongside Cancel and Save. Tapping it closes the edit sheet and triggers the same confirmation dialog as the trash icon on the job card — shows the production name before deleting, then removes from localStorage and Supabase simultaneously.
🧭
Nav Restructure + PM Tools
Alpha V1.3.5.7 · Patch
ImprovedAccount moved into More
Account details, New Calculation, and Sign Out now live inside the More tab. The separate Account tab has been removed — everything is consolidated in one place.
NewHome button in nav bar
The Account tab slot is now a Home button (house icon). Tapping it takes you straight back to the Get Started splash screen from anywhere in the app.
NewJob Brief Generator
Found in More → PM Tools. Fill in Job Name, Job #, Production Company, Shoot Dates, Director, Sound, INT/EXT, Camera type, number of cameras, per-location details, DIT/media notes, and additional notes. Tap Generate Brief for a preview, then Export PDF or Share Brief.
NewCall Sheet Generator placeholder
Visible in More → PM Tools with an amber "Under Construction" badge. Coming in a future release.
FixedProjected income per-day calculation
The monthly income box was dividing the stored day rate by the full job span — a 3-day job showed only one-third of a day's pay per day. job.pay is now correctly treated as a per-day rate and added once per calendar day.
🗓️
Hold Dates + Job Brief Updates
Alpha V1.3.5.7 · Patch
NewHold date range on shoots
New Hold toggle in the Add/Edit Shoot sheet. Appears as a grey gradient bar on the calendar. Hold periods are date ranges — you can add multiple per job. Hold days do not count toward projected income by default.
NewBooked switch on Hold
A toggle inside the Hold section lets you mark the hold as confirmed. When switched on, hold days are treated as booked and contribute to projected income. When off, hold days are invisible to the income calculation.
NewDP & Producer fields in Job Brief
Two new fields in the General section of the Job Brief Generator — DP / Cinematographer and Producer. Both appear in the preview card, PDF export, and plain-text share output.
NewClient presence in Job Brief
New Clients pill selector in Shoot Details — No Clients / On Set / Remote / Zoom. Appears in the brief preview, PDF, and Share text output.
ImprovedNav order
Bottom nav is now Home · Calculator · Calendar · More, left to right. Home sits far-left and returns to the Get Started splash screen.
🎨
Hold Colour Lock
Alpha V1.3.5.7 · Patch
NewHold auto-sets colour to grey
Turning on the Hold toggle immediately forces the event colour to grey and dims the colour picker. You can't accidentally set a hold to a bright colour — it stays visually distinct from confirmed shoots.
NewColour unlocks when Booked
Switching the Booked toggle on re-enables the colour picker so you can assign any colour to a confirmed booking. Switching it back off snaps the colour back to grey and locks the picker again.
🔧
Hold — Data Not Cleared on Toggle Off
Alpha V1.3.5.7 · Patch
FixedHold stuck on after save — root cause
Turning the Hold toggle off hid the section visually but never cleared _subDayState.hold. When the job was saved and reopened, the hold date entries were still present in the data, so openEditJob restored the toggle as checked and the picker locked again. The Hold toggle now immediately clears all hold date entries and resets the Booked checkbox when switched off — so save, close, and reopen produces a clean non-hold job.
⚠️
Meal Penalty Calculation Fix
Alpha V1.3.5.7 · Patch
FixedCamera wrap penalty removed — not in ACCP guidelines
The calculator was charging a 2× meal penalty whenever camera wrapped more than 6 hours after lunch-in. No such penalty exists in the ACCP 2024–2025 guidelines. Camera wrap is for turnaround tracking only. This was the primary source of inflated totals on long shoot days.
FixedSecond meal penalty toggle logic inverted
The condition checked !== false defaulted to "meal provided" when the toggle was absent or unchecked, suppressing the dinner penalty incorrectly. Now reads the toggle directly — if no dinner is entered and the toggle is off, the penalty correctly runs from 6h after lunch-in to wrap at 2× for the first hour then 3× thereafter, per ACCP guidelines.
🧮
Calculator & Invoice Fixes
Alpha V1.3.3.3 · Patch
FixedAfternoon hours no longer include OT in base display
When OT was present, billAfternoon was showing the full actual afternoon (e.g. 7.5h) instead of just the base-fill portion (4h). OT hours now display separately below as always. Fixed in both single-day and multi-day calculators.
FixedCamera wrap penalty removed from all remaining display paths
Removed from the breakdown table, per-day result cards, plain-text copy output, invoice HTML preview, and invoice PDF. Camera wrap field label updated to "Turnaround reference".
FixedInvoice PDF — Description / Rate / Amount columns
Table now has three clear columns with rate detail in the centre (e.g. @ $71.16/hr 1×). Fixes the dark header rect overlapping row text.
FixedDinner penalty used camera wrap as time reference
When no dinner times were entered, dinner penalty was calculated against camWrap instead of yourWrap. Fixed in both invoice preview and PDF export.
📋
Timesheet Updates
Alpha V1.3.3.4 · Patch
NewLine # added to HTML preview
Line # was present in the PDF export and input form but was missing from the on-screen HTML preview fields grid. Now shown alongside Job #.
NewOT columns now show weighted pay hours
The 1x / 1.5x / 2x / 3x columns now show weighted pay hours per tier (e.g. 2 actual OT hours at 1.5× = 3 weighted hours). The Total Pay Hrs column sums all four. Updated across HTML preview, PDF, and Excel.
NewMeal penalty column labels lunch and dinner separately
The Meal Pen. column now shows a breakdown — "Lunch $XX.XX / Dinner $XX.XX" — instead of a single unlabelled total.
FixedTime inputs changed to HH:MM time pickers
All time entry fields changed from decimal number inputs to native time pickers. Eliminates the snapping issue where typing 14:00 was interpreted as 14.5 (2:30pm).
FixedTotal $ now includes meal penalties
Total $ column now uses the full total from the calculator payload (base + OT + all meal penalties) rather than recalculating from hours only.
🧮
Base Day Split Fix
Alpha V1.3.3.5 · Patch
FixedMorning/afternoon display reflects actual 10h split
billMorning = max(6h, actual morning) and billAfternoon = 10h − billMorning. A 6.5h morning (late lunch) correctly shows 6.5h morning + 3.5h afternoon. An early or on-time lunch floors at 6h morning + 4h afternoon. The two lines always add to exactly 10h = base pay.
FixedBillable metric shows weighted pay hours
The Billable card now displays invoice-weighted hours (e.g. 17h weighted for a 14h day with 4h OT) matching the timesheet Total Pay Hrs column.
🔧
Timesheet Transfer & Toggle Fixes
Alpha V1.3.5.7 · Patch
FixedTimesheet rows now populate with calculator data
The timesheet was restoring stale saved form state even when fresh calculation data existed, leaving all rows blank. Fresh calc data now always takes priority over saved state. Navigating from the calculator also clears stale state proactively.
FixedTime restore was corrupting times in HH:MM format
The decToTime() function was applying parseFloat() to strings like "22:30", producing 22.3"22:18" instead of "22:30". Times are now passed as HH:MM strings directly, with decimal fallback for legacy data only.
FixedMP and second meal toggles randomly resetting
renderDayPanels() was rebuilding all panel HTML from scratch, resetting every toggle (meal penalties, second meal, prep day, separate call) back to defaults. All input values and toggle states are now saved before the rebuild and restored immediately after.
📐
Invoice Qty & Floating Point Fix
Alpha V1.3.3.7 · Patch
FixedBillable hours × rate now always equals day total
invoiceHrs is now total / rate rounded to 2 decimal places, so that Invoice qty × rate always equals the exact day total including all meal penalties. Previously used DAY_MIN + ot1×1.5 + ot2×2 + ot3×3 which excluded penalties from the calculation, making the math inconsistent with what you'd enter on an invoice.
FixedBillable hours showing as 18.60 instead of 19
Floating point error: 10 × $71.16 produces 711.5999999999999, making total / rate = 18.999999.... fmtH() was flooring to 18h and rounding 0.9999×60 = 60min, displaying "18h 60m". Fixed by rounding total to 2dp before dividing, rounding invoiceHrs to 2dp, and adding a guard in fmtH() to carry 60min over to the next hour.
NewInvoice qty label in breakdown
The top row of the breakdown card now shows "Invoice qty" with the calculation displayed as Xh × $rate = $total, making it unambiguous what number to enter as quantity on an invoice.
🍽️
Dinner MP Logic Rework
Alpha V1.3.3.8 · Patch
FixedDinner MP now correctly calculated against camera wrap
The "Dinner at camera wrap" toggle (formerly "Second meal provided") now has clear, correct semantics. Toggle ON = dinner was served at camera wrap — penalty runs from the 6h deadline to cam wrap time. Toggle OFF = no dinner provided at all — penalty runs from deadline to your wrap. For the standard test case (lunch in 15:00, cam wrap 21:30), this correctly gives 30min × 2× = $71.16 dinner penalty, producing the correct grand total of $1,352.04.
FixedToggle renamed to "Dinner at camera wrap"
The previous label "Second meal provided" was ambiguous and didn't communicate that the cam wrap field drives the dinner time. New label and sub-text make the two modes explicit. Camera wrap field note updated to "Dinner MP reference & turnaround".
📋
Timesheet PDF Redesign
Alpha V1.3.3.9 · Patch
FixedColumn header labels now visible
Header fill changed to rgb(220,220,228) with setTextColor(20,20,40) applied explicitly per cell before drawing text. The previous approach set fill colour once for all cells, causing jsPDF color state to bleed — text was effectively black-on-grey but the fill wasn't being applied correctly to all cells.
FixedData no longer overlaps in columns
Removed Dinner Out / Dinner In from the main table grid — dinner timing is rare and already captured in the Meal Penalty column. The remaining 13 columns (was 15) now fit cleanly across the 190mm usable width, with the Meal Penalty column widened to 25mm for full label display (e.g. "L $71.16 D $71.16").
NewPer-column totals in TOTAL row
The TOTAL row now shows individual column sums for 1x Hrs, 1.5x Hrs, 2x Hrs, and 3x Hrs, in addition to Total Pay Hrs and Total $. Applied across PDF export, HTML preview, and Excel export.
NewData row backgrounds explicitly white
Each data cell now draws with setFillColor(255,255,255) before rendering, preventing any bleed from the grey header fill into data rows.
🏷️
Rate Type Labels & PDF Credit
Alpha V1.3.5.7 · Patch
FixedHourly and flat rate shown as separate, clearly labeled fields
Previously the PDF always showed a "Daily Rate" field regardless of pay type, which was incorrect for hourly crew. Now: hourly crew see "Hourly Rate" with $X.XX/hr populated; flat rate crew see "Flat Day Rate" with $X/day populated. The other field is left blank. The HTML preview rate label updates to match.
NewHourly / Flat Rate checkboxes in PDF
The badge row now has four checkboxes — Employee, Corporation, Hourly, Flat Rate — with the applicable box in each pair checked. Previously only Employee and Corporation were shown, leaving no indication of the pay structure type.
New© Created using Set Time Calculator
A small copyright credit line appears in the bottom-right of the signature area on every exported PDF, at 5pt in light grey so it's present but unobtrusive.
⏱️
Custom Quarter-Hour Time Picker
Alpha V1.3.4.1 · Feature
NewCustom time picker replaces device time inputs
All time fields in the calculator (Crew call, Your wrap, Lunch out/in, Dinner out/in, Camera wrap) now use a custom floating picker instead of the native device time input. The picker shows only quarter-hour increments (00, 15, 30, 45) for minutes, eliminating the need to scroll through every minute. A clock icon on each field opens the picker; tapping outside or pressing Done closes it. Values are still stored as 24h HH:MM internally so all calculation logic is unchanged.
🕐
12h Clock & Picker Scroll Fix
Alpha V1.3.4.2 · Patch
FixedMinutes column was not showing
The minute items were built correctly but a data-m attribute conflict with the click listener's .closest() call prevented them from rendering selected state. Fixed by using a unified data-val attribute across all columns (hour, minute, AM/PM).
New12-hour clock with AM/PM column
The picker now shows three columns — Hour (1–12), Min (00/15/30/45), and AM/PM — instead of the previous 24h hour column. Selecting AM or PM automatically converts the stored 24h value. The panel is 260px wide to fit all three columns cleanly.
🔧
Picker Scroll & PM Tools
Alpha V1.3.4.3 · Patch
FixedTime picker columns not scrollable
The .tpk-lists wrapper had overflow: hidden which clipped all three inner scroll columns, preventing touch and mouse scrolling entirely. Changed to explicit height: 200px and overflow-y: scroll on each column independently.
NewClaim a Job added to PM Tools
A new "Claim a Job" entry appears in the PM Tools section of the More tab, below Call Sheet Generator, with a green checkmark icon. Marked Under Construction alongside Call Sheet Generator.
📋
Timesheet — Meal Penalty Folded into OT Columns
Alpha V1.3.5.7 · Patch
FixedMeal penalty hours now folded into 1x/2x/3x columns
The Meal Penalty dollar column has been removed. Instead, penalty hours are redistributed into the OT tier columns: late lunch (2× rate) subtracts hours from the 1x column and adds them to 2x; late dinner first hour (2×) similarly; late dinner subsequent hours (3×) add to the 3x column. Example: a 10h day with 30min late lunch now shows 9.5h @ 1× and 0.5h @ 2×, giving Total Pay Hrs = 10.5h and Total $ = $747.18 (vs. the previous incorrect $782.76 with a separate $71.16 MP line).
FixedTotal $ now consistent with folded OT calculation
Total $ uses d.total from the calculator payload, which already correctly accounts for all penalties. The column totals (1x, 1.5x, 2x, 3x) reflect the adjusted values after folding. Applied to PDF export, HTML preview, and Excel export.
📋
Timesheet — Total Hrs Worked Column & Weighted TOTAL Row
Alpha V1.3.5.7 · Patch
NewTotal Hrs Worked column added
A dedicated "Total Hrs" column now appears between the 3x Hrs and Total Pay Hrs columns on the timesheet PDF, HTML preview, and Excel export. Per-row it shows the actual hours worked that day. The TOTAL row shows the sum of all days' worked hours.
FixedTOTAL row now shows weighted hours per OT column
The TOTAL row 1x/1.5x/2x/3x column values now show weighted hours (after multiplier) rather than raw hours — matching the red reference: 1x total = 9.5, 2x total = 1.0 (0.5h × 2), Total Pay Hrs = 10.5. Previously the 2x column total showed 0.5 (raw) instead of 1.0 (weighted).
FixedTotal $ now $747.18 (not $782.76)
Total $ is now computed from the folded adjusted columns (adj1×rate + adj2×rate×2 ...) rather than from the raw d.total payload value. For a 10h day with 30min late lunch: 9.5×$71.16 + 0.5×$142.32 = $676.02 + $71.16 = $747.18.
🔧
Calculator ↔ Timesheet State Restore Fixes
Alpha V1.3.4.6 · Patch
FixedCamera wrap reverting to your wrap time on back-navigation
saveToSession was never including camWrap in the payload. The restore block was using setT('camWrap', day.out) — literally setting camera wrap to your wrap time. Fixed: payload now saves camWrap: minsToHHMM(c.camWrap) as a dedicated field, and the restore uses day.camWrap explicitly.
FixedMeal penalty toggle turning off on back-navigation
Two toggles were never saved or restored when navigating back from the timesheet: (1) mpToggle (the global meal penalties switch) was not included in the payload and always reset to default; (2) secondMealToggle (Dinner at camera wrap) was similarly lost. Both are now saved in the payload (mpOn and secondMealProvided per day) and restored correctly — mpToggle before renderDayPanels(), and secondMealToggle after checkCamWrapVisibility() makes its row visible.
🎬
Claim a Job — PM Job Hub
Alpha V1.3.5.7 · Feature Release
NewClaim a Job screen with PM password wall
A new PM-only section accessible via a password prompt (access code required). Once authenticated, PMs get a full job management hub for posting shoots so crew can find and claim them directly from their own calendar.
NewProduction company database
PMs can build a local database of production companies — each with company name, billing address, and accounting email. Companies are saved to device storage and appear in a dropdown on every new job. Add new companies inline via the "+" option without leaving the form.
NewJob posting with auto-generated job code
Each posted job gets an auto-generated job code derived from the production name and job number (e.g. ACMEAUT-2026-042). Crew can enter this code in their app to find and add the job to their calendar, or the PM can share a direct deep link that opens the app and pre-fills the job automatically.
NewJob details — Awarded status, camera count, shoot info
Each job includes: Awarded toggle (yes/no), camera count stepper, shoot date, number of shoot days, and location field. The location field will drive live weather and traffic data on the crew-facing job page in a future update.
NewDocument uploads — call sheet & shoot schedule
PMs can attach a call sheet (PDF) and shoot schedule (PDF) to each job. These will be accessible from the crew-facing job page. Upload slots show visual confirmation when a file is selected.
NewPosted jobs list with share & remove
All posted jobs appear in a scrollable list at the bottom of the screen. Each entry shows production name, company, job number, camera count, and shoot date, with buttons to share the crew link or remove the job.
NewStart Budget Sheet button (placeholder)
A greyed-out "Start Budget Sheet" button is present on each job, marked Coming Soon. Will launch a budget management workflow in a future update.
FixedTimesheet — duplicate Hrs Worked column removed
The "Hrs Worked" column (beside Lunch In) was identical to the "Total Hrs" column beside Total Pay Hrs. Removed from PDF, HTML preview, and Excel export. Table is now 12 columns.
🔧
Claim a Job — White Screen Fix
Alpha V1.3.5.1 · Patch
FixedClaim a Job showing white screen
The claimjob screen div had style="display:none" hardcoded inline. Inline styles have higher CSS specificity than class rules, so even after showScreen() added the .active class (which sets display:flex), the inline display:none won every time. Removed the inline style.
FixedPM Access modal not opening
The modal div had display:none written twice in its style attribute — a copy-paste duplicate. Cleaned up to a single initial state. Also added claimjob and later myjobs, jobpreview to NAV_SCREENS and updateNav so the nav bar stays visible on those screens.
🎬
Job Preview + My Jobs screens
Alpha V1.3.5.2 · Feature
NewJob Preview screen — crew-facing view
After creating a job, PMs are taken to a crew-facing preview. Shows a meta strip (production, company, job #, shoot date, cameras, job code), live weather via Open-Meteo, embedded Google Maps for the location, a traffic card with Open in Maps link, and collapsible sections for Call Sheet, Shoot Schedule, Job Brief, and Notes.
NewMy Jobs screen — PM dashboard
Password-protected screen listing all created jobs. Each card shows job details, a PM Tools section (Budget Sheet, Payroll, Reports, Settings — all Coming Soon), and Preview / Share / Delete actions. "+ New Job" button in the header. Added to PM Tools in the More tab.
New"Post Job" renamed to "Create Job"
The submit button on Claim a Job is now labelled "Create Job" and navigates to the Job Preview screen instead of showing an inline link.
📅
Calendar Hold + My Jobs Edit
Alpha V1.3.5.3 · Feature
NewAdd to Calendar — shoot days only, default Hold
Crew tapping "Add to My Calendar" on a job preview get the shoot days added as a Hold (grey) automatically. Only shoot days are added — crew add their own prep and wrap days. Duplicate detection prevents double-adding. Syncs to Supabase if logged in.
NewEdit Job in My Jobs
Each job card in My Jobs now has an Edit button that opens a bottom-sheet modal. PMs can update all job fields plus add internal PM Notes (not shown to crew) and Crew Notes (shown on job preview). Saving regenerates the job code.
🔧
Modal Visibility + Calendar Hold Simplified
Alpha V1.3.5.4 · Patch
FixedPM Access modal hard to see
The modal backdrop was rgba(0,0,0,0.5) and the card used the transparent glass style — both blended into the page background. Changed to a solid rgba(0,0,0,0.72) overlay and a solid #f2f2f7 card so the modal stands out clearly on any background.
FixedJob Preview back button went to Claim a Job
Back button now correctly returns to My Jobs (with a fresh mjInit() call) instead of Claim a Job.
FixedConfirmed/Booked toggle removed from calendar
The redundant "Confirmed booking" toggle has been removed. The workflow is now simpler: Hold on = grey (unconfirmed), Hold off = confirmed (your chosen colour). Hold days count toward projected income regardless.
🔧
Timesheet 2dp + Nav Bar Fix
Alpha V1.3.5.7 · Patch
FixedTimesheet hours columns rounded to 1dp instead of 2dp
All hours-related columns in the timesheet (1x, 1.5x, 2x, 3x Hrs, Total Hrs, Total Pay Hrs, and their TOTAL row values) were displaying with 1 decimal place (.toFixed(1)), causing values like 11.3 instead of 11.25 and 0.8 instead of 0.75. All changed to .toFixed(2) across PDF, HTML preview, and Excel.
FixedNavigation bar disappeared — CSS transform containment bug
Root cause: the <nav id="bottomNav"> was nested inside #calSheet, which uses transform: translateY() to animate open/close. In CSS, position: fixed elements lose viewport-relative positioning when inside any ancestor with a transform — they become fixed relative to that transformed ancestor instead. The nav was rendering at top: 1563px (652px below the 911px viewport). Fixed by moving the nav to a direct child of <body> via JavaScript at DOMContentLoaded, ensuring it is never inside a transformed container.
🏗️
Critical Structural Fix — Missing calSheet Close Tag
Alpha V1.3.5.7 · Critical Patch
FixedMore screen, nav bar, and all PM screens broken by unclosed div
Root cause identified via live browser inspection: #calSheet was missing its closing </div> tag. Every screen after it in the HTML — #more, #claimjob, #myjobs, #jobpreview, #jobbrief, and the nav bar — was nested inside #calSheet. Since #calSheet uses transform: translateY(652px) to sit off-screen, everything inside it rendered 652px below the viewport. Fixed by inserting the missing </div> after #whatsNewSheet closes.
FixedWhat's New panel showing too low with no visible close button
#whatsNewSheet was also inside the transformed #calSheet container, rendering 652px below its intended position. Now correctly slides up from the bottom of the screen with its Done button accessible.
FixedMore screen showing as white page
The #more screen content was rendering 652px below the visible viewport due to the same transform containment issue. Fully resolved by the structural fix.