# User Guide — FUJ Web Dashboard ## Getting Started Start the dashboard with: ```bash make web ``` The dashboard is available at **http://localhost:5001** and provides three pages accessible via the green navigation bar at the top. ## Page 1: Attendance & Fees (`/fees`) This page answers the question: **"How much does each member owe this month?"** ### What You See A table with one row per adult member and one column per month. Each cell shows: | Cell | Meaning | |------|---------| | `750 CZK (4)` | Member owes 750 CZK (attended 4 practices that month) | | `200 CZK (1)` | Member owes 200 CZK (attended 1 practice) | | `-` | Member didn't attend — no fee | | `400 (750) CZK (3)` | Fee **overridden** from 750 to 400 CZK (shown in orange) | The bottom row shows **monthly totals** — the total amount expected from all adult members. ### Fee Rules | Practices in a month | Monthly fee | |----------------------|-------------| | 0 | 0 CZK (no charge) | | 1 | 200 CZK | | 2 or more | 750 CZK | ### Source Links At the top, you'll find direct links to: - **Attendance Sheet** — the Google Sheet with raw attendance data - **Payments Ledger** — the Google Sheet with bank transactions --- ## Page 2: Payment Reconciliation (`/reconcile`) This page answers: **"Who has paid, who hasn't, and who owes extra?"** ### Main Table Each cell in the matrix shows the payment status for a member × month combination: | Cell | Color | Meaning | |------|-------|---------| | `OK` | 🟢 Green | Fully paid | | `UNPAID 750` | 🔴 Red | Haven't paid at all | | `300/750` | 🔴 Red | Partially paid (300 out of 750) | | `-` | Gray | No fee expected | | `PAID 200` | — | Payment received but no fee expected | The rightmost column shows each member's **total balance**: - **Positive** (green): Member has overpaid / has credit - **Negative** (red): Member still owes money - **Zero**: Fully settled ### Search Filter Type in the search box at the top to filter members by name. The search is **diacritic-insensitive** — typing "novak" will match "Novák". ### Member Details Click the **`[i]`** icon next to any member's name to open a detailed popup: 1. **Status Summary** — Month-by-month breakdown with attendance count, expected fee, paid amount, and status. Overridden fees are marked with an amber asterisk. 2. **Fee Exceptions** — If any months have manual fee overrides, they're listed here with the override amount and reason. 3. **Payment History** — Every bank transaction matched to this member, showing the date, amount, sender, and payment message. **Keyboard shortcuts** (when the popup is open): - `↑` / `↓` — Navigate to the previous/next member - `Escape` — Close the popup ### QR Code Payments When you hover over an unpaid or partially paid cell, a red **"Pay"** button appears. Clicking it opens a QR code that can be scanned with any Czech banking app. The QR code is pre-filled with: - The club's bank account number - The exact amount owed - A payment message identifying the member and month This makes it trivial to send a payment link to a member who owes money. ### Summary Sections Below the main table, three additional sections may appear: | Section | Shows | |---------|-------| | **Credits** | Members with positive balances (advance payments or overpayments) | | **Debts** | Members with negative balances (outstanding fees) | | **Unmatched Transactions** | Bank transactions that couldn't be automatically matched to any member | --- ## Page 3: Payments Ledger (`/payments`) This page answers: **"What payments has each member made?"** ### What You See Transactions grouped by member name, each showing: - **Date** — When the payment was received - **Amount** — How much was paid (in CZK) - **Purpose** — Which month(s) the payment covers - **Bank Message** — The original message from the bank transfer Transactions are sorted newest-first within each member's section. ### Unmatched Payments Transactions that couldn't be assigned to a member appear under **"Unmatched / Unknown"** — these typically need manual review in the Google Sheet. --- ## Performance Footer Every page shows a **render time** in the bottom-right corner (very small, gray text). This tells you how long the page took to generate. Click on it to reveal a detailed breakdown showing how much time was spent on each step (fetching members, fetching payments, reconciliation, template rendering, etc.). This is mostly useful for debugging slow page loads. --- ## Common Workflows ### "A member asks how much they owe" 1. Open `/reconcile` 2. Search for the member's name 3. Their row shows the exact status per month 4. Click `[i]` for detailed payment history ### "A member wants to pay" 1. Open `/reconcile` 2. Find the unpaid cell 3. Hover and click the red **Pay** button 4. Share the QR code with the member (screenshot or show on screen) ### "I want to see all payments from one person" 1. Open `/payments` 2. Scroll to the member's section (alphabetically sorted) ### "A transaction wasn't matched correctly" 1. Open the **Payments Ledger** Google Sheet (link at the top of any page) 2. Find the row 3. Manually correct the **Person** and/or **Purpose** columns 4. Put any marker in the **manual fix** column to prevent the inference script from overwriting your edit 5. Refresh the web dashboard --- *User guide generated from comprehensive code analysis on 2026-03-03.*