SRS: Dashboard - Common — Journal & Heatmap with 3 Sliders (UC 4.4)
| Field | Value |
|---|---|
| BA in Charge | Trang Nguyen |
| Date Created | 2026-08-09 |
| Version | v1 |
| Document References | RFQ_ Stack Trading Prop Tech V7.pdf (§Daily Journal and Heatmap Endpoints) · RFQ_ Website and Dashboard Implementation V7.pdf (§Part C: Trader Dashboard Implementation, Key Features) |
UC_4.4 — Journal & Heatmap with 3 Sliders
1. Overview
| Field | Content |
|---|---|
| ID | UC_4.4 |
| Use Case | Journal & Heatmap with 3 Sliders |
| Description | Trading Journal screen combining a monthly performance summary (7 aggregate stat cards + a per-grade distribution legend) with a monthly calendar heatmap — one cell per day, showing that day's P&L and self-graded stamp, or a "No trade day" placeholder. Clicking any day cell (traded or not) opens the Journal Entry modal, where the trader records a subjective self-rating across 3 sliders (Entry quality, Exit quality, Plan compliance), picks an overall letter-grade stamp, and writes free-text notes. Same UC for both SIM and LIVE account types. |
| Zapier Flow | — |
| Zapier Table | — |
| 3rd Party | — |
Journal - Day 0.png Trading Journal screen — empty state (no trading days recorded yet in the viewed month). Calendar.png Trading Journal screen — populated state (March 2026). Journal Entry.png Journal Entry modal — self-rating sliders, stamp picker, notes.
2. Trigger
The user selects the "Journal" tab on the Dashboard sidebar (Ref: UC_4.1.2 §2 Screen Description, row 2); or the user clicks a day cell on the calendar (opens the Journal Entry modal, Ref: BR_4.4.6).
3. Pre-conditions
- User is authenticated and has an active SIM or LIVE trading account (Ref: UC_4.1.1).
4. Post-conditions
- The screen displays the monthly summary and calendar heatmap for the selected month; any Journal Entry saved via the modal is persisted and immediately reflected on the calendar and summary cards (Ref: BR_4.4.10).
5. Basic Flow
Flow 1 — View Calendar & Monthly Summary
- On Journal screen load, frontend calls
GET /monthly-journal-data?month=[current month]&year=[current year](Source: RFQ_ Stack Trading Prop Tech V7.pdf §Daily Journal and Heatmap Endpoints "Get Monthly Journal Data"). - Backend returns
aggregate_metrics{monthly_pnl, winning_days, losing_days, win_rate, avg_win_day, avg_loss_day, days_traded, avg_rating}anddaily_records[{date, daily_pnl, rating_score, stamp_grade, notes, self_ratings}]for the month (Ref: BR_4.4.1, BR_4.4.11). - Frontend renders the 7 stat cards from
aggregate_metrics(Ref: BR_4.4.1), the Grade distribution legend computed from the month'sstamp_gradevalues (Ref: BR_4.4.4), and the calendar grid — one cell per calendar day of the viewed month, populated from the matchingdaily_records[]entry if present, otherwise rendered as"No trade day"(Ref: BR_4.4.4). - User clicks the Previous or Next month control → frontend re-calls the endpoint with the new
month/year(Ref: BR_4.4.5) → repeats from step 2.
Flow 2 — Create / Edit Journal Entry
- User clicks any day cell on the calendar — traded or
"No trade day"— → frontend opens the Journal Entry modal for that date (Ref: BR_4.4.6). - [If the date already has an entry] the modal pre-fills the 3 self-rating sliders from
self_ratings{entry_quality, exit_quality, plan_compliance}, the selected stamp fromrating/stamp_grade, and Notes fromtext_content(Ref: BR_4.4.11). [If no entry exists yet for that date] the modal opens with all sliders at their unset state, no stamp selected, and Notes empty; the "Daily P&L" header shows"No trade day"if there is no trade for that date, or$0(colored Yellow) if a trade occurred and closed exactly breakeven (Ref: BR_4.4.6, BR_4.4.10, BR_4.4.14). - User adjusts the 3 self-rating sliders (Ref: BR_4.4.7) and/or selects a stamp (Ref: BR_4.4.8) and/or edits Notes (Ref: BR_4.4.9), then clicks "Save changes".
- Frontend calls
POST /journal-entries(Create Entry) withdate,rating(Integer 1–5, the Stamp),text_content(Notes),self_ratings{entry_quality, exit_quality, plan_compliance}(Ref: BR_4.4.11). - On success, the modal closes and the calendar cell for that date, the 7 stat cards, and the Grade distribution legend refresh immediately to reflect the saved entry (Ref: BR_4.4.10) — control returns to Flow 1 step 3 (re-render from the refreshed data).
6. Exceptional Flow
- User closes the modal without saving (clicks outside the modal, or clicks the close control) while the form is dirty: the modal closes immediately and all unsaved changes are discarded — no confirmation popup is shown (Ref: BR_4.4.10, explicit exception to the system-wide unsaved-data warning pattern).
- WebSocket/API connection drops on initial load: the screen retains its last-loaded month data while the client applies exponential backoff and automatically reconnects, per the shared WebSocket reconnection resiliency rule (CR-14).
- [If
GET /monthly-journal-dataorPOST /journal-entriesfails — HTTP 401/400/404/500/503, timeout, or no network] → see BR_4.4.13 — API Failure Toasts for the toast shown per status code and the resulting state.
7. Business Rules
BR_4.4.1: Monthly Aggregate Stat Cards — Scope & Source
The 7 stat cards (Monthly P&L, Winning Days / Losing Days, Daily Win Rate, Avg Win Day, Avg Loss Day, Avg. rating, Days traded) are scoped to the calendar month currently displayed on the Calendar navigator — not all-time — matching the month/year input parameters of Get Monthly Journal Data (Source: BA confirmation, 2026-08-09, QnA_init_docs.md A-06). Each card maps 1:1 to a field in the endpoint's aggregate_metrics object: monthly_pnl, winning_days/losing_days, win_rate, avg_win_day, avg_loss_day, avg_rating, days_traded (Source: RFQ_ Stack Trading Prop Tech V7.pdf §Daily Journal and Heatmap Endpoints "Get Monthly Journal Data"). Monetary values display per Ref: CR-11; Daily Win Rate displays as a percentage.
Per-card calculation formulas — the source RFQ names each aggregate_metrics field but does not spell out its formula; the definitions below are BA-derived, built on the day-level daily_pnl values already confirmed in BR_4.4.2/BR_4.4.3 and consistent with the winning/losing convention already confirmed elsewhere on the Dashboard (Ref: UC_4.2.4 §BR_4.2.4.1 Gross Profit/Loss split by PnL sign; UC_4.2.5 §Screen Description row 3 Win Rate = winning count ÷ total count × 100). No RFQ/CR/QnA source defines the day-level boundary explicitly — daily_pnl == 0 days are treated as neither winning nor losing (excluded from both counts, consistent with the Gross Profit/Loss convention); this specific boundary treatment is a BA assumption pending client confirmation if the client intends different handling.
- Monthly P&L (
monthly_pnl): sum ofdaily_pnl(Ref: BR_4.4.3) across every calendar day of the viewed month that has a trade.monthly_pnl = Σ daily_pnl[d]for every daydin the month withdaily_pnl[d] ≠ 0. - Winning Days (
winning_days): count of calendar days in the month wheredaily_pnl > 0. Losing Days (losing_days): count of calendar days in the month wheredaily_pnl < 0. - Daily Win Rate (
win_rate):winning_days ÷ days_traded × 100— the percentage of traded days (item 7 below) that closed positive. - Avg Win Day (
avg_win_day): meandaily_pnlacross Winning Days only.avg_win_day = (Σ daily_pnl[d] for d in Winning Days) ÷ winning_days. - Avg Loss Day (
avg_loss_day): meandaily_pnlacross Losing Days only.avg_loss_day = (Σ daily_pnl[d] for d in Losing Days) ÷ losing_days. - Avg. rating (
avg_rating): see BR_4.4.12 for the full client-confirmed formula (Stamp → integer mean → expanded letter-grade scale). - Days traded (
days_traded): count of distinct calendar days in the month with at least one closed or open trade (i.e.daily_pnl ≠ 0, or equivalently the count of days with adaily_records[]entry backed by real trade activity) — this is the denominator used in item 3's Win Rate formula, and equalswinning_days + losing_daysunder the zero-exclusion convention above.
avg_rating ("Avg. rating") displays as a letter-grade label — see BR_4.4.12 for the client-confirmed calculation formula.
BR_4.4.2: Trading-Day Boundary — Exchange Reset Session
The "day" boundary used to bucket a trade into a given calendar cell's daily_pnl is the Exchange Reset session boundary — 18:00 EST for Futures, 17:00 EST for Forex — the same session boundary already established for The Pulse score reset (Ref: UC_4.2.1-4.2.5 §BR_4.2.2.1). This is a deliberate departure from the plain UTC-midnight convention in Ref: CR-08, applied here specifically to keep "trading day" consistent across the Journal and the rest of the Dashboard (Source: BA confirmation, 2026-08-09, QnA_init_docs.md A-07).
BR_4.4.3: Daily P&L Computation — Realized-Only (Closed Positions)
daily_pnl is computed from closed positions only, for both the current trading day and any past trading day — the same closed-position-only data scope used across the rest of the Dashboard's Performance-style widgets (Ref: UC_4.3 §BR_4.3.1). This supersedes the prior "Realized P&L + Unrealized P&L" formula for the current day (Source: BA confirmation, 2026-09-05 — supersedes QnA_init_docs.md A-08).
- Past (already-closed) trading day:
daily_pnl= sum of Realized P&L across every position closed within that day's full session (Ref: BR_4.4.2 for the session-boundary definition of "day"). - Current (still in-progress) trading day:
daily_pnl= sum of Realized P&L across every position closed from that day's session-boundary start (Ref: BR_4.4.2) up to the moment the API is called — i.e. a running total over the elapsed portion of the day so far. Any position still open at call time contributes nothing todaily_pnl(no unrealized component).
Note — no WebSocket live-push for calendar daily_pnl: unlike the Performance screen's PERFORMANCE_UPDATE event (Ref: UC_4.3 §Basic Flow step 7), no WebSocket event pushes an updated daily_pnl to the current day's calendar cell as further positions close during the day. The value shown is a snapshot as of the last GET /monthly-journal-data call (Ref: Basic Flow, Flow 1 step 1) — the frontend only sees a newer figure on the next call to that endpoint (e.g. re-opening the Journal screen, or re-navigating the month). This is a deliberate scope limitation of this endpoint, not an omission (Source: BA confirmation, 2026-09-05).
BR_4.4.4: Calendar Grid — Day Cell Display & Grade Distribution Legend
Each cell in the calendar grid represents one calendar day of the viewed month:
- Traded day: shows the day number,
daily_pnl(Ref: BR_4.4.3), color-coded per BR_4.4.14, and the day'sstamp_gradeicon if an entry exists for that date. - No-trade day: shows the day number and the placeholder text
"No trade day"— nodaily_pnlor stamp is shown. - Ungraded traded day (a trade occurred but no Journal Entry has been saved for it yet): shows the day number and
daily_pnl, color-coded per BR_4.4.14, with an empty/unset stamp placeholder in place of a graded stamp icon (Ref: BR_4.4.10). - Blank day cell (out-of-range day — before the trader's account existed, or after the current real-world day): the cell renders blank — no day-number styling consistent with in-range days, no
daily_pnl, no stamp icon, and no"No trade day"placeholder text. This covers both edges of the calendar range: past days before the account'screated_at/provisioning date (e.g. a trader who just went live sees every day before go-live as blank for the current month), and future days after today (including the common Day 0 case, where a just-activated account shows the entire current month as blank except today onward has not occurred yet either). Blank cells are not clickable — they do not open the Journal Entry modal (contrast with BR_4.4.6, which opens the modal for every in-range day including no-trade days). This is a natural extension of the account-range boundary already enforced on month navigation (Ref: BR_4.4.5), applied at the day-cell level within the currently viewable month.
Grade distribution legend: a summary row counting, for the viewed month, how many daily_records[].stamp_grade values fall into each of the 5 fixed grade options (Ref: BR_4.4.8) — A+, A, B, C-, D.
BR_4.4.5: Month Navigation — Boundaries
The Next month control is disabled once the calendar is showing the current real-world month (future months cannot be viewed). The Previous month control is disabled once the calendar has reached the month the trader's account was created (created_at/provisioning date) — preventing navigation into months that predate the account's existence (Source: BA confirmation, 2026-08-09, QnA_init_docs.md A-11).
BR_4.4.6: Day Cell Click — Opens Journal Entry Modal (Including No-Trade Days)
Clicking any calendar day cell opens the Journal Entry modal for that date — including "No trade day" cells. A Journal Entry is not required to be linked to an actual trade: it is a subjective, date-based self-rating/notes record (Source: RFQ_ Website and Dashboard Implementation V7.pdf §Part C, "Self-Rating Module" — "user-generated and date-based";. When the modal is opened for a date with no trade, the "Daily P&L" header displays the same "No trade day" text as the calendar cell — not $0 — since no PnL value exists for that date (supersedes the prior $0 placeholder; Ref: BR_4.4.14, Source: BA confirmation via user, 2026-08-20). $0 is reserved for an actual breakeven trade (Ref: BR_4.4.14).
BR_4.4.7: Self-Rating Sliders — Entry Quality, Exit Quality, Plan Compliance
Three independent self-rating controls, each a discrete 1–5 scale (click-to-select one of 5 levels; no fractional values): Entry quality, Exit quality, Plan compliance (Source: RFQ_ Website and Dashboard Implementation V7.pdf §Part C, "three specific 5-point evaluation sliders"; BA confirmation, 2026-08-09, QnA_init_docs.md A-05). Each shows its current value as "[N]/5". These 3 sliders are independent of, and do not auto-populate, the "Stamp today's grade" selector (Ref: BR_4.4.8) — the sliders capture detailed self-analysis, while the stamp is the trader's separate, holistic subjective grade (Source: BA confirmation, 2026-08-09, QnA_init_docs.md A-02).
The backend persists and returns all 3 slider values individually via the self_ratings JSON object — see BR_4.4.11 for the confirmed data contract.
BR_4.4.8: Stamp Today's Grade — Manual Selection, Independent of Sliders
The trader manually selects exactly one of 5 fixed grade options — A+, A, B, C-, D — no other grade values exist in the system. The selected stamp is what appears on the calendar day cell (Ref: BR_4.4.4) and feeds the Grade distribution legend (Ref: BR_4.4.4). Selection is independent of the 3 self-rating sliders — there is no auto-suggestion or pre-selection derived from the sliders' values (Ref: BR_4.4.7).
BR_4.4.9: Notes Field
Free-text field for the trader's subjective notes for the date. Standard default length limit applies — Ref: CR-02 §2.2 (Textarea, 500 characters, Overflow: Wrap text) — the source RFQ does not specify a different limit for text_content (Source: BA confirmation, 2026-08-09, QnA_init_docs.md A-14).
BR_4.4.10: Save Behavior — Upsert, No Unsaved-Changes Warning, No Toast, Cascade Refresh
Upsert model: exactly one Journal Entry exists per trader per date. Clicking "Save changes" always overwrites the entry for that date in full (all 3 sliders, stamp, and notes are replaced by the values currently in the form) — there is no support for multiple entries on the same date (Source: BA confirmation, 2026-08-09, QnA_init_docs.md A-10, resolving an "or" ambiguity in the base RFQ text between append and upsert semantics).
No unsaved-changes warning: unlike the system-wide Ref: CR-05 pattern, this modal does not show a confirmation popup when the trader closes it (click outside, or click the close control) with unsaved changes — the modal simply closes and the changes are discarded (Source: BA confirmation, 2026-08-09, QnA_init_docs.md A-15). This is an intentional, documented exception for this UC only.
No toast on save: neither a success nor a failure toast is shown for the "Save changes" action (Source: BA confirmation, 2026-08-09, QnA_init_docs.md A-16). User feedback comes from the modal closing and the calendar/stat cards updating (see Cascade Refresh below).
Cascade refresh: saving an entry immediately updates the affected calendar day cell, and re-triggers the 7 stat cards and the Grade distribution legend for the current month (Ref: BR_4.4.1, BR_4.4.4) — both are derived aggregates over daily_records[], which the new/edited entry is now part of.
Empty-grade placeholder: when the modal is opened for a date with a trade but no saved entry yet, the "Daily P&L" header shows the P&L value with an empty/unset stamp placeholder icon in place of a graded stamp — the same empty placeholder style used for ungraded cells on the calendar (Ref: BR_4.4.4) — until the trader selects a stamp and saves (Source: BA confirmation, 2026-08-09, QnA_init_docs.md A-17).
BR_4.4.11: Backend Data Contract for the 3 Self-Rating Sliders — Client Confirmed
1. Database update (user_journal_entires table): add a new column self_ratings (JSON object). The existing rating column remains the master integer for the Stamp Grade (Ref: BR_4.4.8); text_content remains for Notes (Ref: BR_4.4.9). No separate integer columns are added for the 3 sliders.
2. Create Entry endpoint (POST /journal-entries) — updated input parameters:
| Parameter | Type | Notes |
|---|---|---|
date | String (ISO 8601) | — |
rating | Integer (1–5) | The Stamp (Ref:BR_4.4.8). |
text_content | String | Notes (Ref:BR_4.4.9). |
self_ratings | JSON:{ "entry_quality": int, "exit_quality": int, "plan_compliance": int } | The 3 sliders (Ref:BR_4.4.7), each 1–5. |
3. Get Monthly Journal Data endpoint — updated output: inside the daily_records[] output array, each element now also includes the self_ratings JSON object alongside rating_score, stamp_grade, and notes — giving the frontend everything needed to re-render the 3 sliders and the Notes textarea exactly as last saved (Ref: Basic Flow, Flow 2 step 2).
BR_4.4.12: Avg. Rating Formula
Step 1 — Input mapping (Stamp → integer, rating column):
| Frontend Stamp Selection | Database Integer (rating) |
|---|---|
| A+ | 5 |
| A | 4 |
| B | 3 |
| C- | 2 |
| D | 1 |
Step 2 — Monthly mean: for the viewed month, take the arithmetic mean of every daily_records[].rating (i.e. every saved Journal Entry's Stamp, mapped via the table above) — entries with no saved Stamp are excluded from the mean, consistent with days_traded/journal-entry scope elsewhere in this UC.
avg_rating_mean = (Σ rating[d] for d in daily_records[] with a saved Stamp) ÷ (count of daily_records[] with a saved Stamp)
Step 3 — Output mapping (mean float → avg_rating string, expanded scale, distinct from the 5-value Stamp scale in Step 1):
| Calculated Mean Float | Output String (avg_rating) |
|---|---|
| 4.5 to 5.0 | A+ |
| 4.0 to 4.49 | A |
| 3.5 to 3.99 | B+ |
| 3.0 to 3.49 | B |
| 2.5 to 2.99 | C+ |
| 2.0 to 2.49 | C- |
| 1.0 to 1.99 | D |
Note the Step 3 output scale is intentionally wider than the Step 1 input scale (it includes B+/C+, which do not exist as selectable Stamp options) — this is expected per the client's confirmed logic, and is why avg_rating can display a label the trader never directly picked.
BR_4.4.13: API Failure Toasts — GET /monthly-journal-data / POST /journal-entries
When either Journal API call fails, the frontend shows the toast below matching the returned HTTP status (or the no-response case for timeout/network loss). Both APIs share the same status-to-toast mapping — 401/500 reuse the system-wide TE-AUTH-01/TE-SYS-01 toasts already used across other Dashboard UCs (e.g. UC_4.6.1 §7); 400/404/503 get 3 new Journal-scoped toasts (TE-JRN-01..03) since no existing entry in list-toast-popup.md covered those statuses.
| ID toast | HTTP Status | Trigger | Toast Content | Type |
|---|---|---|---|---|
| TE-AUTH-01 | 401 | Session / access token expired. | "Your session has expired. Please log in again" | Error |
| TE-JRN-01 | 400 | POST /journal-entries — server-side validation rejects the payload (malformed date, rating outside 1–5, notes over 500 chars) despite passing client-side checks. Does not apply to GET /monthly-journal-data, which takes no body. | "We couldn't save your entry. Please check your inputs and try again" | Error |
| TE-JRN-02 | 404 | Either API — route/resource not found. Edge case, not expected in normal navigation. | "We couldn't load this data. Please refresh and try again" | Error |
| TE-SYS-01 | 500 | Either API — unhandled server error. | "Unable to connect. Please check your network and try again" | Error |
| TE-JRN-03 | 503 | Either API — service temporarily unavailable (maintenance/overload). | "The service is temporarily unavailable. Please try again in a few minutes" | Error |
| TE-SYS-01 | Timeout / no network (no HTTP response at all) | Either API — request timed out client-side or the browser has no network. | "Unable to connect. Please check your network and try again" | Error |
No auto-retry on any of the above — the trader retries by re-navigating the month, re-clicking "Save changes", or reloading the page. (Source: BA addition per user request, 2026-08-19.)
BR_4.4.14: Daily P&L Color Coding — Green / Red / Yellow
Every displayed daily_pnl value on this UC — the calendar day cell (Ref: BR_4.4.4, traded/graded and traded/ungraded cells) and the Journal Entry modal's "Daily P&L" header (Ref: BR_4.4.6) — is color-coded by sign:
| Color | Condition |
|---|---|
| Green | Profit —daily_pnl > $0 |
| Red | Loss —daily_pnl < $0 |
| Yellow | Breakeven — a trade occurred anddaily_pnl is exactly $0 |
(Source: BA confirmation via user, 2026-08-20.)
8. Screen Description
Screen A — Trading Journal (Calendar)
| No. | Field Name | Field Type | Displaying rule / Behaviour rule |
|---|---|---|---|
| 1 | Monthly P&L | Label | Displaying rule:- aggregate_metrics.monthly_pnl for the viewed month. Monetary value display: Ref: CR-11. Formula: Ref: BR_4.4.1 item 1.Motion: Link motion. |
| 2 | Winning Days / Losing Days | Label | Displaying rule:- aggregate_metrics.winning_days / losing_days, shown as "[W] W / [L] L". Formula: Ref: BR_4.4.1 item 2.Motion: Link motion. |
| 3 | Daily Win Rate | Label | Displaying rule:- aggregate_metrics.win_rate, shown as a percentage. Formula: Ref: BR_4.4.1 item 3.Motion: Link motion. |
| 4 | Avg Win Day | Label | Displaying rule:- aggregate_metrics.avg_win_day. Monetary value display: Ref: CR-11. Formula: Ref: BR_4.4.1 item 4.Motion: Link motion. |
| 5 | Avg Loss Day | Label | Displaying rule:- aggregate_metrics.avg_loss_day. Monetary value display: Ref: CR-11. Formula: Ref: BR_4.4.1 item 5.Motion: Link motion. |
| 6 | Avg. rating | Label | Displaying rule:- aggregate_metrics.avg_rating, letter-grade label. Formula: Ref: BR_4.4.12.Motion: Link motion. |
| 7 | Days traded | Label | Displaying rule:- aggregate_metrics.days_traded, integer count. Formula: Ref: BR_4.4.1 item 7.Motion: Link motion. |
| 8 | Month navigator — Previous | Button (Icon) | Displaying rule:- Disabled once the calendar reaches the trader's account-creation month. Ref: BR_4.4.5.Behaviour rule:- On click: loads the previous calendar month.Motion: Link motion. |
| 9 | Month navigator — label | Label | Displaying rule:- Currently viewed month/year, e.g. "March 2026".Motion: Link motion. |
| 10 | Month navigator — Next | Button (Icon) | Displaying rule:- Disabled once the calendar reaches the current real-world month. Ref: BR_4.4.5.Behaviour rule:- On click: loads the next calendar month.Motion: Link motion. |
| 11 | Grade distribution legend | Label | Displaying rule:- 5 counters, one per grade option (A+, A, B, C-, D), each showing "×[count]" for the viewed month. Ref: BR_4.4.4.Motion: Link motion. |
| 12 | Calendar day cell — traded (graded) | Link | Displaying rule:- Day number + daily_pnl (color-coded Green/Red/Yellow, Ref: BR_4.4.14) + stamp_grade icon. Ref: BR_4.4.3, BR_4.4.4.Behaviour rule:- On click: opens the Journal Entry modal (Screen B) pre-filled with the existing entry. Ref: BR_4.4.6.Motion: Link motion. |
| 13 | Calendar day cell — traded (ungraded) | Link | Displaying rule:- Day number + daily_pnl (color-coded Green/Red/Yellow, Ref: BR_4.4.14) + empty/unset stamp placeholder (no entry saved yet). Ref: BR_4.4.4.Behaviour rule:- On click: opens the Journal Entry modal (Screen B) with sliders/stamp/notes blank. Ref: BR_4.4.6.Motion: Link motion. |
| 14 | Calendar day cell — no-trade day | Link | Displaying rule:- Day number + placeholder text "No trade day". Ref: BR_4.4.4.Behaviour rule:- On click: opens the Journal Entry modal (Screen B); "Daily P&L" header shows "No trade day" (not $0). Ref: BR_4.4.6, BR_4.4.14.Motion: Link motion. |
| 15 | Calendar day cell — blank (out-of-range) | Label | Displaying rule:- Blank cell: no day-number styling, no daily_pnl, no stamp icon, no "No trade day" text. Shown for days before the account's created_at/provisioning date or after today (Ref: BR_4.4.4 "Blank day cell"). Covers the Day-0/just-activated case.Behaviour rule:- Not clickable — does not open the Journal Entry modal.Motion: Link motion. |
Screen B — Journal Entry (modal)
| No. | Field Name | Field Type | Displaying rule / Behaviour rule |
|---|---|---|---|
| 16 | Daily P&L header | Label | Displaying rule:- The date being edited, and either: "No trade day" text if no trade occurred that date, or daily_pnl for that date color-coded Green/Red/Yellow if a trade occurred (Ref: BR_4.4.6, BR_4.4.14) — and the current stamp (or empty placeholder if ungraded, Ref: BR_4.4.10). Monetary value display: Ref: CR-11.Motion: Link motion. |
| 17 | Entry quality | Discrete Rating Selector (1-5)¹ | Displaying rule:- Discrete 1–5 scale, shown as "[N]/5". No default value pre-selected for a new entry. Ref: BR_4.4.7.Behaviour rule:- Click-to-select one of 5 levels.Motion: Link motion. |
| 18 | Exit quality | Discrete Rating Selector (1-5)¹ | Displaying rule:- Same as row 17. Ref: BR_4.4.7.Behaviour rule:- Click-to-select one of 5 levels.Motion: Link motion. |
| 19 | Plan compliance | Discrete Rating Selector (1-5)¹ | Displaying rule:- Same as row 17. Ref: BR_4.4.7.Behaviour rule:- Click-to-select one of 5 levels.Motion: Link motion. |
| 20 | Stamp today's grade | Radio Group | Displaying rule:- Options: A+, A, B, C-, D, all visible. Default: A+ . Ref: BR_4.4.8.Behaviour rule:- Single-selection, independent of rows 17–19.Motion: Link motion. |
| 21 | Notes | Textarea | Displaying rule:- Placeholder: "Enter notes". Max: 500 characters, Overflow: Wrap text. Ref: CR-02. Ref: BR_4.4.9.Motion: Link motion. |
| 22 | Save changes | Button (Primary) | Behaviour rule:- On click: calls POST /journal-entries (Ref: BR_4.4.11) with the current form values — date, rating, text_content, and self_ratings{entry_quality, exit_quality, plan_compliance} — as an upsert. On success: closes the modal and refreshes the calendar/stat cards (Ref: BR_4.4.10). No toast is shown. Impact:- Overwrites any existing entry for the date in full (Ref: BR_4.4.10); updates the 7 stat cards and Grade distribution legend for the current month (Ref: BR_4.4.1, BR_4.4.4).Motion: Link motion. |
| 23 | Close control | Button (Icon) | Behaviour rule:- On click: closes the modal immediately, discarding any unsaved changes — no confirmation popup. Ref: BR_4.4.10.Motion: Link motion. |
¹ Discrete Rating Selector (1-5) is a proposed new entry for the Field Type Glossary (skill_shared_validation_rules.md §5) — pattern candidate confirmed non-blocking by BA (QnA_init_docs.md A-13), pending the glossary being formally updated.
Changelog
| Date | Version | Updated item | Before | After | Notes |
|---|---|---|---|---|---|
| 2026-08-19 | v1.1 | §6 Exceptional Flow | Only 2 bullets: modal-close-without-saving (no confirmation popup) and WebSocket/API drop on initial load (CR-14 reconnect). No bullet coveredGET /monthly-journal-data or POST /journal-entries failing outright (5xx/timeout/no network). | Added 1 bullet pointing to newBR_4.4.13 for the full per-status-code toast table. | User request: describe toast messages for timeout/5xx on the calendar list API and failed Journal-entry saves. |
| 2026-08-19 | v1.2 | BR_4.4.13 (new) | Did not exist. | Added — full per-HTTP-status toast table (401/400/404/500/503/504 + timeout/no-network) forGET /monthly-journal-data and POST /journal-entries, with an ID toast / HTTP Status / Trigger / Toast Content / Type / Resulting State column layout. 400/404/503/504 use 4 new toasts (TE-JRN-01..04, added to list-toast-popup.md v3.7); 401/500 reuse existing TE-AUTH-01/TE-SYS-01. | User follow-up request: move the toast list out of §6 Exceptional Flow into a dedicated Business Rule table with columns ID toast/HTTP status/Trigger/Toast content/Type, covering 401/400/404/503/500/504.⚠️ Open follow-up carried over: this rule covers only network/infra/validation failures, not the business-outcome "did my save succeed" toast — BR_4.4.10's "No toast on save" rule (QnA_init_docs.md A-16, 2026-08-09) is left unchanged. Recommend the BA re-confirm with the client that A-16 was scoped to business-outcome only, since the two cases were not explicitly distinguished when A-16 was originally confirmed. |
| 2026-08-19 | v1.3 | BR_4.4.13 (table trim) | 7 rows (incl. 504/TE-JRN-04) × 6 columns (incl. Resulting State). §6 bullet listed "HTTP 401/400/404/500/503/504". | Removed the 504 row (TE-JRN-04 no longer referenced here) and removed the Resulting State column — table is now 6 rows × 5 columns (ID toast/HTTP Status/Trigger/Toast Content/Type), matching the user's exact spec. Resulting-state info kept as one shared sentence below the table instead of a per-row column. §6 bullet updated to "HTTP 401/400/404/500/503" and no longer references "resulting screen/modal state". Intro paragraph updated from "4 new Journal-scoped toasts (TE-JRN-01..04)" to "3 new Journal-scoped toasts (TE-JRN-01..03)". | User request: "bỏ row lỗi 504 và cột resulting state" (remove the 504 row and the Resulting State column).TE-JRN-04's definition is left untouched in list-toast-popup.md — only its reference row here was removed. |
| 2026-08-20 | v1.4 | BR_4.4.14 (new) — Daily P&L color coding | No color rule existed fordaily_pnl anywhere in this UC — calendar cells and the modal header displayed the value uncolored. | AddedBR_4.4.14: Green (profit, > $0) / Red (loss, < $0) / Yellow (breakeven, exactly $0). Applied to calendar day cells (traded/graded and traded/ungraded, rows 12–13) and the Journal Entry modal's "Daily P&L" header (row 16). Flagged 2 open items: (a) divergence from the Win/Loss Dot Grid (UC_4.2.5 BR_4.2.5.1), which uses Grey — not Yellow — for the same breakeven concept; (b) whether the no-trade-day $0 placeholder should render Yellow or stay uncolored — left ⏳ pending client confirmation. | Client-confirmed rule relayed by user, 2026-08-20: "Green: Profit (Greater than $0), Red: Loss (Less than $0), Yellow: Breakeven (Exactly $0)". |
| 2026-08-20 | v1.5 | BR_4.4.14 (both open items resolved); BR_4.4.6; Basic Flow Flow 2 step 2; Screen Description rows 14 & 16 | (a) Grey-vs-Yellow cross-widget divergence left as an open question. (b) No-trade day showed$0 in the modal header (Ref: BR_4.4.6) and on Screen Description row 14; unclear whether that $0 should be colored. | (a) Confirmednot a conflict — Win/Loss Dot Grid's Grey and this UC's Yellow are separate, intentional per-widget conventions; Yellow stays unchanged here. (b) Confirmed no-trade day no longer shows $0 anywhere — calendar cell and modal header both show "No trade day" text instead (BR_4.4.6, Screen Description rows 14 & 16, Basic Flow Flow 2 step 2 all updated). $0 is now reserved exclusively for an actual breakeven trade (a trade occurred, daily_pnl computed to exactly $0), and displays colored Yellow in that case. | Client-confirmed via user, 2026-08-20: "2 màu hiển thị ở 2 UC này là khác nhau, không xung đột. Giữ nguyên màu vàng khi breakeven ở UC này." + "Ở No trade day sẽ không hiển thị $0 chỉ hiển thị No trade day. Khi có giao dịch nhưng không lỗ không lãi thì sẽ hiển thị $0 và màu vàng tương ứng." |
| 2026-09-05 | v1.6 | BR_4.4.3 — Daily P&L formula changed from Realized+Unrealized to Realized-only; note added on no WebSocket live-push | Current (still-open) trading day: daily_pnl = Realized P&L + Unrealized P&L (same Net P&L formula as Daily Loss Limit enforcement). Past day: Realized-only. No note on whether the calendar's daily_pnl updates live via WebSocket. | Current-day formula changed to Realized-only, matching past-day scope: daily_pnl = sum of Realized P&L of positions closed from the day's session-boundary start up to the API-call moment; open positions contribute nothing. Rationale: all Performance-screen data (Ref: UC_4.3) is sourced from closed positions only, so the Journal's daily_pnl is kept consistent with that scope. Added an explicit note: unlike UC_4.3's PERFORMANCE_UPDATE event, no WebSocket event pushes calendar daily_pnl updates — the value is a snapshot as of the last GET /monthly-journal-data call. | User request: clarify (1) current-day daily_pnl is computed the same way as past days — from closed positions in the day so far, not Realized+Unrealized; (2) explicitly note the calendar day cell's PnL has no WebSocket live-push. |