Skip to content

[CSM][Mobile] Time cards (My sheets / All / Approvals, filters, approve-reject) - #1129

Merged
rksk merged 21 commits into
wso2-open-operations:dev-app-csm-portalfrom
Hesara2003:feature/csm-microapp-timecards
Jul 13, 2026
Merged

rksk merged 21 commits into
wso2-open-operations:dev-app-csm-portalfrom
Hesara2003:feature/csm-microapp-timecards

Conversation

@Hesara2003

@Hesara2003 Hesara2003 commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

Adds the Time Cards feature to the CSM microapp (mobile), replacing the ComingSoon placeholder reached at More → Time Cards. Brings mobile parity with the webapp's time-cards views.

Scope note: This is the view + approve/reject slice. Logging a new time card (the create form with the activity breakdown + approver picker) is intentionally out of scope here — it's a larger form and best on desktop — and is tracked separately.

Goals

  • Three tabs — My sheets, All (read-only), and Approvals (approver-only).
  • View weekly time sheets and approve / reject submitted cards on mobile.
  • Per-tab filters matching the webapp.

Approach

  • services/timecards.ts — infinite (paged) React Query options for My sheets / All / Approvals + the approve-reject mutation, backed by POST /time-cards/search and PATCH /time-cards/{id}. Cards from every loaded page are flattened and grouped into weekly sheets in one pass.
  • utils/timecard.ts — ISO-week grouping, state → chip meta, minute formatting, filter model + helpers.
  • types/timecard.dto.ts / timecard.model.ts — wire shapes + the portal model and mapper (time is in minutes).
  • components/timecards/ — TimeSheetCard (tap-to-expand week accordion), TimeCardStateChip, TimeCardReviewDialog (reason required on reject), TimeCardFiltersSheet.
  • pages/TimeCardsPage.tsx — the tabbed workspace; the active tab's query is lifted here so the filter sheet can offer the loaded work-item / engineer options.
  • Filters per tab: My sheets → project, work item, state, date range · All → project, work item, engineer, state, date range · Approvals → project, work item, engineer, date range. Project is server-side (projectIds); work item + engineer are client-side over the loaded cards (no search endpoint for either); state is client-side; date range maps to startDate/endDate.
  • Pagination: infinite scroll (50 / page, the backend cap) via an IntersectionObserver sentinel — the mobile equivalent of the webapp's page controls.
  • Scope is only the feature — the bottom nav and routing are unchanged (owned by dev-app-csm-portal).
  • Also pins the three @wso2/oxygen-ui* packages to 0.2.1/0.4.0 so the microapp installs — the 0.6.1 currently on the branch isn't published to npm, so a fresh npm install fails on ETARGET.

User stories

As a CS engineer, I can review my logged time by week on mobile; as an approver, I can approve or reject submitted time cards on the go.

Release note

Adds the Time Cards feature (My sheets / All / Approvals tabs, per-tab filters, approve-reject, infinite scroll) to the CSM microapp.

Documentation

N/A — internal CSM microapp UI, no external doc surface affected.

Automation tests

  • Unit tests: N/A — the microapp has no test runner configured yet.
  • Verified against staging: My sheets / All / Approvals load, filters narrow the list, approve/reject round-trips, and pagination scrolls through the full result set.

Security checks

Test environment

  • Type-check (tsc) and npm run lint passing locally.

Summary by CodeRabbit

  • New Features
    • Added a complete Time Cards experience with personal, all-cards, and approvals views.
    • Browse weekly time sheets with expandable details, status chips, totals, and non-billable indicators.
    • Filter by project/work item/engineer, status chips, and date range (with active filter count).
    • Approvers can approve or reject submitted cards; rejections require a reason comment.
    • Includes infinite scrolling with loading, error, and end-of-results messaging.
  • Style
    • Added consistent status chip styling and improved time/date presentation.
  • Chores
    • Updated Oxygen UI package versions used by the microapp.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c25cfe64-6629-434e-b74f-3910f2d1030e

📥 Commits

Reviewing files that changed from the base of the PR and between e1d828d and b29afb1.

📒 Files selected for processing (2)
  • apps/csm-portal/microapp/src/pages/TimeCardsPage.tsx
  • apps/csm-portal/microapp/src/utils/timecard.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/csm-portal/microapp/src/pages/TimeCardsPage.tsx

📝 Walkthrough

Walkthrough

Adds a complete timecard experience with typed API models, weekly grouping, filtering, infinite loading, approval/rejection dialogs, state indicators, and role-aware tabs.

Changes

Timecards feature

Layer / File(s) Summary
Contracts and domain utilities
apps/csm-portal/microapp/src/types/*, apps/csm-portal/microapp/src/utils/timecard.ts, apps/csm-portal/microapp/src/types/user.model.ts
Defines timecard DTOs, portal models, user roles, filters, state metadata, date helpers, and weekly sheet grouping.
Search and decision services
apps/csm-portal/microapp/src/config/endpoints.ts, apps/csm-portal/microapp/src/services/timecards.ts
Adds paginated search, client-side filtering, weekly view shaping, and approve/reject mutations.
Filter and review components
apps/csm-portal/microapp/src/components/timecards/*, apps/csm-portal/microapp/package.json
Adds filter, review, state-chip, weekly-sheet, and card-row components, with updated Oxygen UI package versions.
Page orchestration
apps/csm-portal/microapp/src/pages/TimeCardsPage.tsx
Replaces the placeholder with tabs, infinite scrolling, filters, loading states, approval mutations, and review dialogs.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TimeCardsPage
  participant timecards
  participant TimecardAPI
  TimeCardsPage->>timecards: request timecard pages
  timecards->>TimecardAPI: POST /time-cards/search
  TimecardAPI-->>timecards: return paginated cards
  timecards-->>TimeCardsPage: return grouped weekly sheets
  TimeCardsPage->>timecards: submit approval or rejection
  timecards->>TimecardAPI: PATCH /time-cards/{id}
  TimecardAPI-->>TimeCardsPage: return updated timecard
Loading

Possibly related PRs

Suggested labels: Type/New Feature, Area/Frontend

Suggested reviewers: rashmika998, cloby99, rksk

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the new mobile Time Cards feature and its main actions.
Description check ✅ Passed The description covers purpose, goals, approach, user stories, release note, tests, security, and environment; only non-critical template sections are missing.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/csm-portal/microapp/src/utils/timecard.ts (1)

163-167: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Guard sheetStatus against empty input.

Array.every() returns true for an empty array (vacuous truth), so sheetStatus([]) returns "approved" — misleading for a sheet with no cards. The function is currently only called with non-empty arrays from groupIntoSheets, but it's exported and could be called from new code.

🛡️ Proposed fix
 export function sheetStatus(cards: CsmTimeCard[]): TimeSheetState {
+  if (cards.length === 0) return "submitted";
   if (cards.some((c) => c.state === "rejected")) return "rejected";
   if (cards.every((c) => c.state === "approved" || c.state === "processed")) return "approved";
   return "submitted";
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/csm-portal/microapp/src/utils/timecard.ts` around lines 163 - 167, Add
an explicit empty-array guard at the start of sheetStatus so sheetStatus([])
does not reach the cards.every() check and return "approved"; return the
appropriate non-approved state consistent with the existing submitted fallback,
while preserving the current rejected and approved behavior for non-empty card
arrays.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/csm-portal/microapp/src/pages/TimeCardsPage.tsx`:
- Around line 198-199: Update the empty-state condition in the TimeCardsPage
render flow to return EmptyState only when sheets is empty and !hasNextPage. For
empty filtered pages with more results available, continue rendering the
sentinel and loading UI so fetchNextPage can load later matches.

---

Nitpick comments:
In `@apps/csm-portal/microapp/src/utils/timecard.ts`:
- Around line 163-167: Add an explicit empty-array guard at the start of
sheetStatus so sheetStatus([]) does not reach the cards.every() check and return
"approved"; return the appropriate non-approved state consistent with the
existing submitted fallback, while preserving the current rejected and approved
behavior for non-empty card arrays.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6b22c2b5-2bb5-4a30-be15-7358ba8f1de1

📥 Commits

Reviewing files that changed from the base of the PR and between d4c5862 and 7c60068.

⛔ Files ignored due to path filters (1)
  • apps/csm-portal/microapp/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (13)
  • apps/csm-portal/microapp/package.json
  • apps/csm-portal/microapp/src/components/timecards/TimeCardFiltersSheet.tsx
  • apps/csm-portal/microapp/src/components/timecards/TimeCardReviewDialog.tsx
  • apps/csm-portal/microapp/src/components/timecards/TimeCardStateChip.tsx
  • apps/csm-portal/microapp/src/components/timecards/TimeSheetCard.tsx
  • apps/csm-portal/microapp/src/config/endpoints.ts
  • apps/csm-portal/microapp/src/pages/TimeCardsPage.tsx
  • apps/csm-portal/microapp/src/services/timecards.ts
  • apps/csm-portal/microapp/src/types/index.ts
  • apps/csm-portal/microapp/src/types/timecard.dto.ts
  • apps/csm-portal/microapp/src/types/timecard.model.ts
  • apps/csm-portal/microapp/src/types/user.model.ts
  • apps/csm-portal/microapp/src/utils/timecard.ts

Comment thread apps/csm-portal/microapp/src/pages/TimeCardsPage.tsx Outdated
@Hesara2003

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Hesara2003
Hesara2003 requested a review from rksk July 12, 2026 18:14
Comment thread apps/csm-portal/microapp/src/utils/timecard.ts Outdated
@rksk

rksk commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Known limitation: state-filtered progress count ("N of Y") is misleading

services/timecards.ts never sends states on the wire (documented in the code — the search endpoint 500s when states is combined with a large projectIds scope, same limitation the webapp's time-cards feature works around). State filtering happens client-side, over cards already fetched.

Side effect: TimeSheetsView.total/loaded (computed in toView()) are derived from the backend's pre-state-filter page/total, but the rendered sheets have already been narrowed by the client-side state filter. Once a user applies a state filter, the "N of Total" line in TimeCardsPage/SheetListView no longer describes what's actually on screen — e.g. it can read "3 of 200" when 200 was never the size of the filtered set.

Proposing to handle this in two parts:

  • FE mitigation (this repo, follow-up): derive loaded/total from post-state-filter counts instead of echoing the backend's unfiltered total, or drop the "of Y" denominator entirely while a state filter is active.
  • Full fix: the real root cause is the backend's inability to apply states server-side alongside a large projectIds scope — that's a backend/entity-service improvement, tracked separately outside this repo, not something this PR should attempt.

Not a blocker for this PR (mirrors the same workaround the webapp already ships with), just flagging so it isn't mistaken for a new mobile-only bug.

@Hesara2003

Copy link
Copy Markdown
Contributor Author

Done in b29afb1. When a state/work item/engineer filter is on, the count now shows just the shown count (e.g. "12 cards") instead of "N of total", since that total is pre filter. Kept "N of total" when unfiltered. Server side states fix out of scope here as you said.

@rksk
rksk merged commit 6fb8bd2 into wso2-open-operations:dev-app-csm-portal Jul 13, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants