Add Personal Timesheet View to Me Tab on Dashboard - #469
Open
Dharp02 wants to merge 46 commits into
Open
Conversation
Step 1 of the redesign plan. Bottom nav tabs are now Dashboard, Huddle, Clock (center FAB), Tickets, Teams. Settings is still reachable via the avatar dropdown in the header, matching the prototype's priority order.
Step 2 of the redesign plan. Adds a CSS-only override that turns the @mieweb/ui Modal into a bottom-sheet on mobile: slides up from the bottom, full width, rounded top corners only, capped at 88dvh with internal scroll. Applies to every consumer of the shared Modal (tickets, teams, org, invite, confirm-delete, feedback, media, etc.) without forking the component. Desktop behavior is unchanged.
Step 3. Huddle now uses AppPage flush + fill so PostCards stretch to the viewport edges on mobile (no side gutter, no card radius). Tabs, composer, drafts, and search input keep px-4 mobile gutter so they still look inset. Desktop keeps the max-w-4xl reading column (Phase 2 will tighten this to max-w-2xl). No changes to composer logic or post rendering.
The quick-stats grid in DashboardPage.tsx already uses 'grid grid-cols-2 gap-3', which satisfies the mobile 2-column requirement from the redesign plan. Me/Team scope is controlled by the existing OrgTeamSwitcher / TeamContext, not a separate toggle inside the page, so no layout change is needed for step 4. Numbers populate correctly for both personal and team scopes.
Step 5. ClockPage was already a single-column stack (banner status -> plan/wrap-up composer -> primary action -> punch-clock display). On mobile the primary action row (Post plan and clock in / Post wrap-up and clock out / Clock in / Clock out / Break) now stacks vertically with each Button spanning w-full so the tap target reaches the full column width. Desktop keeps the horizontal flex-wrap row via sm:flex-row + sm:w-auto. Plan-first gate logic in useClockToggle is untouched -- all 11 tests in useClockToggle.test.ts still pass.
Replaces the anchored Dropdown popover with the shared Modal primitive: - Mobile: full-width bottom sheet (existing Modal CSS from step 2) - Desktop: centered dialog (existing Modal CSS from step 10) - Organization select + Team list with member counts + '+ New team', matching design/redesign-prototype/index.html's OrgTeamSwitcher exactly - Portals the Modal to document.body so it escapes AppHeader's backdrop-blur containing block (backdrop-filter creates a new containing block for position:fixed descendants, which was pinning the sheet near the header instead of the viewport) - Preserves existing features not in the prototype: org role labels, pending join-request badges, awaiting-approval section
- Header trigger now matches the prototype's stacked two-line layout: brand mark + bold team name on top, muted 'Org name ▾' below — replacing the single-line 'Org > Team' pill. - Replaced the large translateY(100%) slide-up keyframe with the prototype Modal's actual animation: a quiet fade + 4px settle (150ms ease-out). The prototype never really 'slides' a large distance — it docks the sheet to the bottom and just fades/settles it in, which is what read as clean instead of a 'jump'.
- AppPage gains an optional titleActions slot so pages can render controls on the same row as the page title (right-aligned), used here for the Me/Team segmented toggle from the redesign prototype. - DashboardPage: 'Me' (default) shows the signed-in user's own hours today, open/closed/high-priority tickets, and running timers; 'Team' shows the existing team-wide aggregates unchanged. - The toggle is always visible now (previously personal-team users had the team members / time-logged sections silently hidden via isPersonalTeam) — switching to Team on a personal team just shows a team of one instead of hiding the section.
The prototype's desktop sidebar renders the Organization select + Team list + '+ New team' inline, always visible — no header button/modal. Extracted that content into OrgTeamSwitcherPanel (shared with the mobile bottom sheet) and render it directly in Sidebar.tsx's brand block for the expanded desktop rail. The header pill + Modal in OrgTeamSwitcher is now md:hidden (mobile-only) since desktop no longer needs it — mobile behavior is unchanged.
…prototype" This reverts commit b7923fd.
… switcher - Teams page: replace tabs with always-visible Members/Pending sections - Add horizontal-scroll team pill switcher (Personal + selected team lead, rest follow) - Consolidate Rename/Delete/Copy/Share into Team Settings modal; keep code+copy under team name - Restore per-member 3-dot menu (Make/Remove Admin, Set Password, Remove Member) for all rows, including self (minus self-demote/remove) - Compact icon-only Create/Join Team buttons in page title actions - Move admin Timesheet view from Teams to Dashboard's Team tab with Overview/Timesheet toggle and deep-link support - Scope the mobile bottom-sheet Modal treatment to only the org/team switcher modal, restoring default centered dialogs everywhere else - Update e2e tests and notification deep links to match
Give the plan/wrap-up composer the same Photo/Video/Doc/Pulse/Ticket/ @Mention bar as the Huddle composer (extracted into shared ComposerAttachButtons/ComposerChips so both stay in sync), and match the redesign prototype's status card (bold elapsed-session timer instead of the wall clock) and Recent sessions list.
- Override @mieweb/ui's mobile full-screen defaults (min-h-dvh, rounded-none) so all modals render as centered popups on every screen size - Add horizontal margin on small screens so modals don't touch viewport edges - Move org-switcher bottom-sheet rules outside the 767px media query so the bottom-sheet treatment applies on all screen sizes (not just mobile)
Drop the avatar circle and nested flex wrapper from the expanded composer, trim its padding, and widen the feed's max-width from 2xl to 4xl so it isn't stranded in a narrow strip on wide dashboards.
Replace text "Copy" link with a tight code badge + copy + share icon button group so the invite code row stays uncluttered. Share uses the Web Share API with a clipboard fallback for desktop.
Match Clock's column width to Huddle's (max-w-2xl -> max-w-4xl). Also drop the opacity/saturate dimming on the bottom-nav Clock In/Out FAB when a plan or wrap-up is pending — it's a plain link to the clock page, not a disabled control, so it shouldn't look blocked.
The per-row "..." menu used the plain library Dropdown, which positions its menu absolutely inside the ticket list's overflow-y-scroll container. Per the CSS overflow spec, once one axis is scrollable the other axis clips too, so the menu was silently cut off for rows near the bottom of the list -- the same class of bug FilterDropdown already works around elsewhere in this file. Portal the menu to document.body with fixed coordinates computed from the trigger's rect, same pattern.
- Add meView state ('overview' | 'timesheet') to the Me tab
- Add Overview / Timesheet secondary toggle under Me tab
- Render AdminTimesheetPanel pre-loaded with the current user when meView is 'timesheet'
- Add userToTeamMember helper to convert TimecoreUser to TeamMember shape
AppHeader: add a bell icon beside the profile avatar that navigates to /app/notifications, matching the pattern already used in Huddle and the bottom nav. Sidebar: add a footer row showing the app version/build (real values via App.getInfo() on native/TestFlight, falling back to the web build's VITE_APP_VERSION otherwise) plus a "Test push notification" button wired to the same notifications.testPush endpoint Settings already uses.
⏳ Preview Build In ProgressDocker image is building — this takes a few minutes (Meteor bundle compilation happens at image-build time, not container start time). A new comment will appear here when the preview is ready or if the build fails. |
npm run format (prettier --check .) was failing on 5 files that had drifted from Prettier's style, blocking the Frontend Checks job on PR #469.
The composer was wrapped in an extra px-4 inset on mobile that PostCard never had, so it rendered as a narrower floating bar next to full-bleed post rows below it. Drop the wrapper padding so both are flush edge-to-edge on mobile, matching PostCard's own sizing.
- BottomNav: replace Teams tab with a bottom-sliding "More" sheet containing Teams, Organization, and Profile (mirrors the redesign prototype); remove the mobile hamburger drawer from AppHeader/Sidebar since it's no longer reachable. - ddp.ts/TeamContext: add DdpClient.onDisconnect() fired the instant the socket drops, and reset the teams subscription's ready guard on disconnect so a reconnect's transient partial team list can no longer silently reset the selected team back to Personal. - TicketsPage: clamp filter dropdown menus (Team/Priority/Status/Assignee) to the ticket list card's actual bounds after mount, fixing menus rendering partly outside the card/viewport on mobile.
UserDropdown: hide Admin, Developers, and Help sections on mobile widths (hidden md:contents) — only Profile, Settings, and Sign out remain in the top account menu on mobile. BottomNav: More sheet gains drill-down Admin (Enterprise, Members), Developers (Seeder), and Help (Report an Issue, Share Your Feedback, TestFlight) cards with a back button, mirroring the desktop account menu.
DashboardPage: persist the Me/Team toggle to localStorage (app:dashboardTab) so navigating away and back no longer silently resets it to Me. DashboardPage: add a Recent Activity card showing everyone's published plan/wrap-up huddle posts for the team (live via the huddlePosts.byTeam DDP subscription), each row linking to /app/huddle?postId=<id>. Huddle page: support the postId deep link — scrolls to and briefly highlights the matching post once the feed loads, then strips the query param. PostCard: accept a highlighted prop (ring highlight) and a stable id for scroll-to-post targeting.
DashboardPage: only show the Recent Activity card for actual teams — a personal workspace has no 'everyone' to show activity for. Rows now use a plain <button> instead of the @mieweb/ui Button (which enforces a fixed h-10 and was clipping/overlapping the two-line content on mobile), with larger avatar, more padding, and clamped 2-line post preview so it's no longer congested on mobile or web.
The indigo highlight ring around a deep-linked post (from the dashboard's Recent Activity feed) now clears as soon as the user clicks/taps anywhere, instead of only after the 2.5s timeout.
Contributor
There was a problem hiding this comment.
Pull request overview
Implements a broad UI redesign across the app shell (mobile bottom nav + desktop sidebar/header), and moves/extends timesheet functionality so both personal and admin team timesheets are accessible from the Dashboard (including deep-link support).
Changes:
- Adds Dashboard “Me/Team” scoping, including a personal Timesheet view on “Me” and an admin-only Team Timesheet view (migrated from Teams) with deep-link support.
- Reworks navigation/shell: mobile “More” bottom sheet, revised sidebar ordering, updated Org/Team switcher UI, and a notifications bell in the header.
- Updates Huddle/Tickets/Clock/Teams layouts and e2e tests to match the new routes and UI structure.
Reviewed changes
Copilot reviewed 26 out of 26 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/e2e/timesheet/timesheet-calculation-fixes.spec.ts | Updates deep-link navigation and UI interactions to land on Dashboard Team Timesheet. |
| tests/e2e/teams/teams.spec.ts | Moves admin timesheet filter assertions from Teams → Dashboard Team tab. |
| tests/e2e/teams/profile-routing.spec.ts | Removes obsolete “Members tab” navigation now that members are always visible. |
| src/ui/UserDropdown.tsx | Hides Admin/Developers/Help sections on mobile to align with mobile “More” sheet pattern. |
| src/ui/Sidebar.tsx | Reorders nav items and adds sidebar footer app info + test push action; removes mobile drawer. |
| src/ui/OrgTeamSwitcher.tsx | Rebuilds the org/team switcher to use an @mieweb/ui Modal + Select with team list. |
| src/ui/BottomNav.tsx | Adds new mobile bottom nav (Dashboard/Huddle/Clock/Tickets/More) and “More” bottom sheet. |
| src/ui/AppPage.tsx | Adds titleActions to support right-aligned controls alongside the page title. |
| src/ui/AppLayout.tsx | Adjusts toast sizing/centering behavior for desktop widths. |
| src/ui/AppHeader.tsx | Removes mobile hamburger and adds notifications bell button linking to notifications page. |
| src/styles.css | Adds global Modal overrides and OrgTeamSwitcher modal styling/animations. |
| src/pages/Huddle.tsx | Adds deep-link-to-post highlighting and adjusts layout spacing for mobile/desktop. |
| src/lib/TeamContext.tsx | Fixes a reconnect race by resetting subscription readiness on DDP disconnect. |
| src/lib/ddp.ts | Adds onDisconnect listener support to allow callers to reset “ready” state on socket drop. |
| src/features/tickets/TicketsPage.tsx | Fixes clipped menus by portaling dropdowns and adds mobile horizontal filter chip row. |
| src/features/teams/TeamsPage.tsx | Removes timesheet from Teams UI, adds pill-style team switcher, refactors settings/rename UX. |
| src/features/huddle/PostCard/index.tsx | Adds post id anchor + optional highlight ring for deep-link navigation. |
| src/features/huddle/HuddleComposer.tsx | Extracts attachment/ticket/mention UI into a shared component. |
| src/features/huddle/ComposerAttachments.tsx | New shared composer attachment controls and chips (reused by Huddle + Clock). |
| src/features/dashboard/DashboardPage.tsx | Implements Me/Team tabs, personal timesheet view, admin team timesheet view, and recent activity. |
| src/features/clock/ClockPage.tsx | Redesigns clock page structure, adds shared composer attachments, and shows recent sessions. |
| meteor-backend/server/timers.js | Updates notification deep-link URL to point to Dashboard Team Timesheet. |
| meteor-backend/server/notify-core.js | Updates notification deep-link URL to point to Dashboard Team Timesheet. |
| meteor-backend/package.json | Adds production server-only build scripts for Meteor backend. |
| docs/redesign-implementation-prompt.md | Adds implementation plan documentation for the redesign phases and constraints. |
Comment on lines
+143
to
+160
| /* Org/team switcher Modal — always a bottom sheet on all screen sizes. | ||
| * `align-self:end` pushes it to the bottom of the library's centering flex | ||
| * container without forking the Modal component. | ||
| */ | ||
| [data-slot='modal'].org-switcher-modal { | ||
| align-self: end !important; | ||
| min-height: auto !important; | ||
| max-height: 88dvh !important; | ||
| width: 100% !important; | ||
| border-radius: 1rem 1rem 0 0 !important; | ||
| animation: none !important; | ||
| } | ||
| [data-slot='modal'].org-switcher-modal[data-state='open'] { | ||
| animation: mieweb-modal-fade-in 150ms ease-out both !important; | ||
| } | ||
| [data-slot='modal'].org-switcher-modal[data-state='closed'] { | ||
| animation: mieweb-modal-fade-out 120ms ease-in both !important; | ||
| } |
Collaborator
Author
There was a problem hiding this comment.
Committed the suggested change
The border above the like/comment/share row now stretches to the card's full corners (-mx-5/px-5 instead of -mx-1) instead of stopping short. Clicking the author avatar or name in the huddle feed now navigates to their profile page.
Meteor.users has no idGeneration override, so its _id is the default Random.id() format (17-char alphanumeric) — not the 24-char hex ObjectId the /app/profile/:id route's regex expected. Raw userIds without a known username (e.g. huddle post authors) were falling through to the username branch and failing lookup ('Unknown user'), including when clicking your own profile from the Huddle feed. Broadened the ID regex to also match Meteor's default 17-char user id format.
Bumped the dashboard's Recent Activity feed cap from 6 to 10 posts; older activity remains reachable via 'View all' on the Huddle page.
Addresses Copilot review comment on PR #469: the .org-switcher-modal overrides (align-self:end, width:100%, top-only rounding) applied unconditionally, forcing a bottom sheet on desktop too. This contradicted OrgTeamSwitcher's own doc comment and the redesign spec (bottom sheet on mobile, centered dialog on desktop). Wrapped the overrides in the same 767px mobile breakpoint used elsewhere in this file.
design/redesign-prototype/index.html was a static mockup used as design reference during the redesign work — not needed in the shipped PR.
- AppHeader: hide the clock-page shortcut on /app/clock so its 'Clock in' aria-label doesn't collide with the ClockPage's own Clock In button (Playwright strict-mode fail).
- ClockPage e2e page object: .clock-banner → .clock-status; status text 'On shift' → 'Clocked in'; plan gate text 'Write a plan before starting this session' → 'Plan before you clock in' — the underlying DOM was renamed during the redesign.
- Team switcher tests (team-qr-share, team-auto-accept, org-invite-by-email, timesheet-calc): getByRole('menuitem', {teamName}) → getByRole('dialog').getByRole('button', {teamName}); the switcher renders a modal of plain buttons now, not a menu.
- team-qr-share: 'Share team QR code' button lives inside Team Settings; the main teams page opens the share modal via 'Share team invite link'.
- teams: 'Copy' button is now 'Copy team code'; disambiguate the created team header by asserting the h3 CardTitle instead of unscoped getByText.
- dashboard: scope sidebar nav-item assertions to the 'Main navigation' nav, since the dashboard body now has its own Timesheet/Team tabs.
- timesheet-calc admin view: scope the 'Timesheet' tab click to <main> to skip the sidebar's identically-named nav button.
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.
Overview
This branch implements the full mobile/desktop UI redesign for TimeHuddle — bringing the app to parity with the redesign prototype across layout, navigation, and interaction patterns — plus several quality-of-life fixes and feature additions on top.
Changes by Commit
Navigation & Shell
OrgTeamSwitcher
Dashboard
Clock Page
Huddle
Tickets
Teams Page
Modals & Toasts
New Features
AdminTimesheetPanelDocs
design/Acceptance Criteria
npm run typecheckandnpm run lintpass clean