development → staging - #776
Merged
Merged
Conversation
Deploy: staging → main
Deploy: staging → main
storybook build has no --base option (that's Vite-only), so the build-storybook step has been failing on every push to main since the mkdocs conversion, leaving the deployed site stuck on a stale pre-mkdocs Storybook-only build. The base path is already set via viteFinal in .storybook/main.ts, so the flag was redundant anyway. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QSwWkchRGye37hoCmEfDCz
Fix GitHub Pages docs deploy: remove invalid storybook --base flag
react-docgen's resolveToValue recurses infinitely on a let variable that is conditionally assigned and then reassigned multiple times, causing "Maximum call stack size exceeded" during `npm run build-storybook`. Compute API_BASE_URL once via a helper instead of reassigning it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…verflow Fix Storybook build: react-docgen stack overflow in config.ts
Deploy: staging → main
Replaces the truncation-prone `points_today` badge with three easy daily goals (logged in, completed an activity, 3+ minutes recorded) plus a one-off AP bonus for clearing all three in a day. - progression.daily_goals: live goal-state computation and idempotent bonus award, gated by a new DailyGoalAward(player, date) row - Wired into both activity-completion paths (ActivityTimer.complete and offline logging), not just the timer flow - GameSettings.daily_goals_completion_bonus_ap controls the bonus amount - MeViewSet.daily_goals replaces today_points with the full goal state - Removed the now-dead PlayerCharacterLink.player_time_today/points_today - Frontend: DailyGoalsBadge replaces TodayPointsBadge Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014hFSsXRtBgoJX7HTqdmTEb
Replace map-view badge with daily goals + completion bonus
fix: standardize timer duration formatting
can_link was a single BooleanField written independently by signals.py, spawn_characters/generate_characters, admin actions, and link_services, so any one writer could clobber another's reason with no way to tell why a character ended up unlinkable. Replace it with a read-only property derived from independent reasons: manual reservation (new Character.is_reserved field, surfaced in admin as "Reserved"), age (Character.is_underage), and active link (Character.is_npc's existing check). Leaves a documented extension point for the population-centre lock from #681. Since can_link is no longer a DB column, add CharacterQuerySet.linkable()/CharacterManager as the SQL-level equivalent for the filter/exists-check call sites (users/utils.py, character_services.character_has_available, CharacterFilter). Also: - Drop the mark_as_canlink admin action in favour of ticking the new "Reserved" checkbox directly; add a CanLinkListFilter since a property can't sit in ModelAdmin.list_filter directly. - Remove the now-unnecessary can_link recompute-on-link-change signal plumbing in character/signals.py - nothing to keep in sync once it's computed live. - Migration drops the can_link column and adds is_reserved (no backfill - there's no way to recover which characters were historically reserved, which is the bug this fixes). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…vation feat: derive Character.can_link instead of storing it (#682)
Fixes multi-session desync (#759): if a player has more than one session open (two tabs, phone + laptop), starting, labelling, or submitting an activity in one had no effect on the others, since each session's timer state was purely local React state. Backend: - Add gameplay.utils.broadcast_activity_timer(timer), reusing the existing player_{id} channel group and send_group_message/"action" message pattern from gameplay/signals.py and utils.control_timers. - Call it after every timer mutation: start/pause/reset/complete (BaseTimerViewSet), and set_activity/label_activity/complete (ActivityTimerViewSet), plus both auto-complete paths in tasks.py (disconnect grace period and the stale-connection sweep) so a tab left open elsewhere is told the timer already closed out. - No consumer changes needed: TimerConsumer's existing generic "action" handler already relays any {"type": "action", ...} group message straight to the socket. Frontend: - Extend WebSocketActionMessage with the new "activity_timer_update" action and its data payload. - Wire the previously-stubbed handleGlobalWebSocketEvent dispatcher with an onActivityTimerUpdate option. - WebSocketContext calls activityTimer.loadFromServer on receipt, mirroring GameContext's existing bootstrap load (same limitSeconds/is_premium resolution). loadFromServer just overwrites local state, so a session echoing its own update is a harmless no-op. Tests: broadcast_activity_timer call verified for start/complete/ set_activity/label_activity and both auto-complete Celery tasks.
feat: sync activity timer across a player's open sessions
The name field was the only field in the shared edit modal (used by Tasks, Skills, Projects, Categories, and Activities panels) that required an explicit "Save" click, unlike the due-date and parent-task fields, which already autosave on blur/change. - Name now autosaves on blur/Enter, matching the due-date pattern. The explicit "Save" button is gone since there's nothing left to save manually; "Cancel" is now just "Close". - A panel-local "Saved"/"Couldn't save" indicator (bottom-right of the modal) reports the outcome of any autosave in the modal, including the Tasks panel's due-date and parent-task fields. Chose a lightweight indicator scoped to the modal over the existing global toast system, since that toast is a large, centered, attention-grabbing element meant for occasional events (e.g. level-ups) — too heavy for a frequent, low-stakes autosave confirmation. - onEdit (and the per-panel handleEdit implementations) now accept optional onSuccess/onError callbacks, forwarded into each mutation's mutate() call so failures surface as a warning instead of failing silently.
…rows - TasksPanel: the "Parent task" select was hidden entirely once a task had a parent, with no way to revert it. It now always renders (still disabled when the task itself has subtasks, to prevent nesting). - PlayerItemList: child tasks were rendered nested inside the parent's own <li>, structurally and visually boxed inside it. They now render as independent rows, siblings of other top-level items, indented via a width/margin modifier so the right edge still lines up with the parent's. - gameplay/tasks.py: fix a circular import (gameplay.utils -> gameplay.services.xp_modifiers -> gameplay.tasks -> gameplay.utils) that crashed web/celery on startup, by deferring the broadcast_activity_timer import into the two functions that use it. Fixes #765.
fix: keep parent-task field editable and render subtasks as indented rows
…with modal actions - right: sp.$padding-base was a two-value shorthand (invalid for a single-value offset), so the browser dropped the declaration and the indicator fell back to its static (bottom-left) position, overlapping the Close button. Use $spacing-md instead. - Debounce "Saving…" by 150ms so fast autosaves go straight to "Saved" instead of flashing the interim state. - Move the indicator into the actions row and vertically center it with the Close/Delete buttons instead of anchoring to the modal's bottom edge; bump contrast (border, stronger shadow, bolder text) so it reads clearly without changing its size. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…63-t3l7dz # Conflicts: # frontend/src/components/TasksPanel/TasksPanel.tsx
Autosave the name field in PlayerItemList's edit modal
Scale due-date formatting smoothly on both sides of now: days (2-6), then weeks[, leftover days] out to 8 weeks, then months, matching the pattern already used by "last worked on". Future dates beyond ~6 months still fall back to an absolute date; past dates keep counting months uncapped. Closes #760 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Extend formatDueAt with weeks/months granularity
BuildingDetail.tsx's residentLine() was simplified in 37f09c6 to drop the " — idle"/" — walking" activity-status suffix, but the tests weren't updated to match, leaving BuildingDetail.test.tsx and Map.test.tsx failing on development. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mur33yGv419VMfAaKxjaGS
Adds a "Log activity" flow (issue #704) for recording work done outside a running timer: a "+" entry point next to the activities summary opens a modal to search/enter a task, split hours+minutes duration, and a completion date/time (capped at today via the native date picker). Submits to the existing backend endpoint and surfaces its XP-eligibility messaging — the backend remains authoritative on whether XP is actually awarded; the client only does obvious sanity-checks (positive duration, required fields). Also fixes two things this surfaced along the way: - Input.tsx dropped the native `required` attribute (kept aria-required) — it was silently blocking form submission in favor of the browser's own validation UI, overriding the app's styled error messages. - Modal.module.scss's .modalContent had overflow-x: hidden with no horizontal padding, clipping the focus ring on any full-width input flush against its edge. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mur33yGv419VMfAaKxjaGS
feat: add offline activity logging modal
gaidheal1
marked this pull request as ready for review
August 13, 2026 23:21
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
User-visible improvements (UVIs)
Features
Fixes and UX improvements
Developer experience and quality
Character.can_linkis now derived instead of stored, removing a source of stale data (Derive Character.can_link from underlying reasons instead of a single stored flag #682)Technical notes
No new migrations or env vars required for this batch.
Test plan
Generated by Claude Code