CAP Last Seen Report (Web)
I built a small, browser‑based tool to generate a “last seen” attendance report directly from a CAP eServices Post Attendance Report CSV, with optional enrichment from a membership roster CSV. There’s no server and no upload — everything runs locally in your browser for speed and privacy.
Repo: https://github.com/abnormalend/cap-last-seen-report
Features
- Process CAP Post Attendance Report CSV to compute the most recent date each member (CAPID) was “seen”.
- Optional Membership CSV enrichment to determine expiration status.
- Sort by CAPID, Full Name, or Last Seen Date.
- Export results as CSV or PDF.
- 100% client‑side: privacy‑friendly and fast.
Quick Start
- Open
web/index.htmlin your browser (double‑click or use your browser’s Open File dialog). - If your browser has strict local file policies, serve it with a simple local server (e.g.,
python -m http.server). - Choose files in the UI:
- Post Attendance Report CSV (required)
- Membership CSV (optional)
- Pick sorting options (default: Last Seen Date, newest first) and click Generate.
- Export using Download CSV or Download PDF.
Input CSV Formats
Post Attendance Report CSV (required)
Expected headers (case‑sensitive): CAPID, FullName, StartDate, Present, Excused
Accepted StartDate formats include:
M/d/yyyy h:mm a(e.g.,10/3/2024 6:00 PM)M/d/yyyy H:mm(e.g.,10/03/2024 18:00)yyyy-MM-dd HH:mm:ss(e.g.,2024-10-03 18:00:00)M/d/yyyy(e.g.,10/03/2024)
A row counts as “seen” if Present == "X" OR Excused == "X".
Membership CSV (optional)
Expected headers (case‑sensitive): CAPID, Expiration1
Accepted Expiration1 formats include:
d LLL yyyy(e.g.,31 Aug 2026)d LLLL yyyy(e.g.,31 August 2026)M/d/yyyy(e.g.,08/31/2026)
Expiration logic:
- If CAPID exists in membership: Expired if
Expiration1 < today; show that date (YYYY‑MM‑DD). - If CAPID not in membership: show
NOT IN ROSTER. - If
Expiration1cannot be parsed: treat as not expired (cell empty).
Processing Rules
- Consider a member “seen” if
PresentorExcusedequalsX(case‑insensitive). - Only valid CAPIDs and parsable
StartDatevalues are considered. - Output is one line per unique CAPID with the latest seen date.
- When membership CSV is present, a single
Expiredcolumn is added:- Empty = not expired
- Date = expired on that date
NOT IN ROSTER= CAPID missing from membership CSV
Output Columns
Without membership CSV:
CAPID,FullName,LastSeenDate
With membership CSV:
CAPID,FullName,LastSeenDate,Expired
Dates are ISO‑formatted as YYYY‑MM‑DD.
PDF Export Settings
- Paper: US Letter
- Orientation: Portrait
- Margins: 0.5”
- Title: 18 pt; Header: 11 pt; Body: 10 pt
Tech Stack
- Papa Parse — robust CSV parsing
- Luxon — date parsing/formatting
- jsPDF + AutoTable — PDF generation
Privacy & Security
All processing happens locally in your browser. No data is uploaded to any server.
Troubleshooting
- Nothing happens on Generate:
- Make sure the Post Attendance Report CSV is selected and contains required headers.
- Check the browser console for errors.
- Some rows are missing:
- Only rows with a valid CAPID and a parsable
StartDateare considered. - Only rows where
PresentorExcusedisXare counted as “seen”.
- Only rows with a valid CAPID and a parsable
Expiredcolumn showsNOT IN ROSTER:- The CAPID isn’t present in your Membership CSV or headers don’t match.
- Dates not parsed:
- Confirm formats match one of the accepted patterns above; trim whitespace.
- PDF looks cramped:
- Try a different sort or export CSV and adjust column widths in a spreadsheet.
Links
- Live demo: https://cap-last-seen-report.pages.dev
- Source code: https://github.com/abnormalend/cap-last-seen-report
- Latest releases: https://github.com/abnormalend/cap-last-seen-report/releases