Skip to content

web: delete a category and report how many subscriptions were uncategorised #224

Description

@rghvgrv

Parent

#196 — PRD: Angular web client for SubVora (parity minus reminders)

What to build

Deleting a user's own category. Subscriptions using it are not deleted — they become uncategorised, because losing a grouping beats losing the record — and the API reports how many were affected. The dialog must state that consequence before the fact, and the app must report the count afterwards.

Implementation Steps

  1. API method — add remove(id) to core/api/categories-api.service.ts returning { subscriptionsUncategorized } on 200, 404 for a system default or another user's category.
  2. Consequence dialog — reuse shared/confirm-dialog.component.ts (from the subscription delete slice) with copy that names the category and states plainly that its subscriptions will become uncategorised, not deleted.
  3. Store method — remove(id) in categories.store.ts drops the item on success and returns the count; a 404 reports "Not found." and reloads.
  4. Report and propagate — show "N subscriptions are now uncategorised" (correctly singular for one, and a plain confirmation for zero), then refresh the subscriptions list store if loaded so those rows move to the uncategorised group.
  5. Spec — categories.store.spec.ts additions: a successful delete removes the item and reports the returned count; zero affected still confirms; the subscriptions store is refreshed only when it holds data.

Agent Routing

agent_routing:
  complexity_hint: easy
  required_capability: balanced
  parallel_safe: true
  cost_preference: low
  speed_preference: balanced
  ownership_scope:
    - src/SubVora.Web/src/app/features/categories/**
    - src/SubVora.Web/src/app/core/api/categories-api.service.ts
  verification:
    - cd src/SubVora.Web && npx ng test --no-watch

Technical Context Snapshot

Current stack in scope

  • UI: Angular (20+) standalone components with signals and built-in control flow, Angular Material (Material 3) as the only component library, SCSS. Static SPA — no SSR, no service worker.
  • State: signal-backed injectable stores, one per domain area, mirroring the MAUI ViewModel split in src/SubVora.Mobile/ViewModels one-to-one. No NgRx.
  • API access: hand-written models plus one service per API controller under src/SubVora.Web/src/app/core/api. Enums travel as JSON strings (JsonStringEnumConverter in Program.cs), so TypeScript string-literal unions are exact.
  • Backend consumed unchanged: ASP.NET Core net10.0, /api/v1/, JWT bearer in the Authorization header, tokens in JSON bodies (no cookies).
  • Tests: Angular CLI unit-test builder (Vitest runner; Karma is deprecated) with HttpTestingController. Stores, interceptors, mappers and utils only — no component-DOM or browser automation.

Dependencies in scope

  • Reuse: @angular/*, @angular/material, rxjs, and the utilities already added under src/SubVora.Web/src/app/core. No chart library, no date library, no HTTP wrapper library.
  • New dependency additions allowed for this slice: no. If a dependency looks unavoidable, stop and raise it on the issue rather than adding it.

Architecture alignment

  • Preserve the repo's load-bearing rules (CLAUDE.md): burn-rate maths is server-side and counts cycles, never days; currency conversion is a read-time projection and stored amounts are never overwritten; nothing advances next_billing_date on a timer; provider matching stays one SQL query; the mobile SQLite cache stays a read-only mirror.
  • There is deliberately no shared DTO project. Web models mirror the API's JSON contract by convention — a contract change means editing both sides.
  • create-git-issue provides routing hints only and assigns no concrete agent or model.
  • run-with-it remains the final runtime routing authority.

Integration touchpoints

  • Consumes DELETE /api/v1/categories/{id} returning DeleteCategoryResult { subscriptionsUncategorized }.
  • Server behaviour: subscriptions are uncategorised rather than deleted, and system defaults answer 404.
  • The subscriptions list groups by category name, so affected rows must move to the uncategorised group after a delete.

Acceptance criteria

  • The confirmation states that subscriptions will become uncategorised rather than deleted.
  • After deleting, the affected count is reported and those subscriptions appear in the uncategorised group.
  • System default categories offer no delete action.

Blocked by

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestready-for-agentReady for autonomous agent execution

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions