Skip to content

release: Rework sharing, list copying, and the product action clusters - #161

Merged
OffCrazyFreak merged 8 commits into
mainfrom
dev
Aug 7, 2026
Merged

release: Rework sharing, list copying, and the product action clusters#161
OffCrazyFreak merged 8 commits into
mainfrom
dev

Conversation

@OffCrazyFreak

@OffCrazyFreak OffCrazyFreak commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Release of everything currently on dev, 34 commits.

Sharing

  • The share modal is one access select (Privatno, Pregled, Kupnja, Uređivanje) rather than a toggle plus a level picker, saving on change with a toast and a live region.
  • A list is shared by its own id, replacing the rotating capability token. docs/SHARING.md records why revocation was given up.
  • The shared-list banner states the exact level, and the list card icon shows it at a glance.

Copying a list

  • Copying asks what to carry: products, the ticks with their captured prices, and the sharing settings, which stays owner-only and is enforced server side.
  • The copy's name is a prefilled input rather than a fixed <naziv> (Kopija), so renaming and copying are one action. The field is shared with the create and edit modals.
  • The copy runs as one endpoint, so a failure partway cannot leave a half-populated list behind.

Products and watchlist

  • Product and shopping list action clusters reordered, with the unreachable mobile actions dropdown removed and the card's action buttons hidden on narrow viewports.
  • Tracked and already-listed products carry a pen-badged icon.
  • The watchlist threshold prefills, detects real changes only, and gates its save button on a parsed schema rather than isValid.
  • The price stack is shared between the product and watchlist cards.

UI and accessibility

  • Select chevrons are visible again, select icons match the chevron and the search bar, and SelectItem has an icon slot.
  • Banner honours its own size, and the layout no longer clips the last card's shadow.

Notes

  • Frontend only, no backend schema changes beyond the sharing work already on dev.
  • CI is green on 3af9090.
  • The pre-release multi-tool dev-vs-main review was skipped at my request for this release.

🤖 Generated with Claude Code

Changes:
- Add Stage 4, which detects the run's artifacts, branches and worktrees and proposes removing them
- Require AskUserQuestion before any deletion, with scratch output and triage docs asked separately
- Refuse to delete a branch with unpushed commits or an open PR, even when selected
- Note that a deleted reviews/ is not a broken state, since the runners recreate it

A cycle left scratch folders, triage docs and a fix branch behind with nothing in
the skill to clear them, so they accumulated across runs and muddied the resume
detection the skill reads on every invocation.

Notes:
Cleanup is opt-in per run rather than automatic. A triage doc is the only record
of the findings the user chose to skip, and a fix branch can hold the only copy
of unpushed commits, so nothing here is safe to sweep on the agent's initiative.
Changes:
- Derive isFormValid in use-watchlist-item-form by parsing the schema over the
  current values, and gate the submit button on it

formState.isValid only refreshes when RHF runs the resolver, and seeding the
prefill through reset does not run it, so the only pass was the mount one over
the empty defaults. A first-time watch opened with a valid prefilled threshold
but a dead Prati button, until switching watch mode triggered an unrelated
validation pass and woke it up.

Notes: this mirrors isEdited, which already compares values to baselines rather
than trusting RHF's dirty flags. The resolver stays in place and still owns the
messages under the field, so nothing is marked red before it is touched.
Changes:
- Extend the prefill gotcha with the validity half: formState.isValid only
  refreshes when the resolver runs, a seeding reset does not run it, and a
  form gating an untouched prefill should parse the schema itself

The dirty half of this trap was already written down; the validity half is what
left a prefilled first-time watch unsavable until the mode was switched.
Changes:
- Extract the list name field into shopping-list-title-field.tsx, shared by the create, edit and copy modals
- Give the copy modal a react-hook-form title input, prefilled with "<naziv> (Kopija)" and submitted through the modal's form id
- Shorten the prefill by code point so the suffix fits the schema's ceiling, read off the schema rather than restated
- Trim the title inside shoppingListRequestSchema, so whitespace cannot pass min(3) and reach the backend blank
- Key CopyListModal by list id in the entity outlet, so the lingering instance cannot carry a typed name to the next list
- Grow the option row icon to size-6 and the checkbox to size-8 with a size-6 tick
- Relabel the option rows to "Kopiraj sve proizvode" and "Označeno i spremljene trgovine"

Copying always produced "<naziv> (Kopija)" and left renaming as a second trip through the edit modal. The name is now an input the user can change before the copy exists, and the field is the same one the create modal uses rather than a second copy of it.

Notes:
- The progress row's description still mentions prices while its new label does not. Deliberate, and the copy does carry the prices.
Changes:
- Note in SHARING.md that the copy modal asks for a name, prefilled with the "(Kopija)" suggestion
- Add the copy hook and the shared title field to the file table

Keeps the sharing reference matching what the copy modal now does.
Changes:
- Remove the "Kopirat će se samo naziv popisa." paragraph that appeared when no option was ticked

The modal is vertically centred, so the hint appearing and disappearing shifted the whole dialog as options were toggled. The name field and the three rows already say what the copy will contain.
@netlify

netlify Bot commented Aug 7, 2026

Copy link
Copy Markdown

Deploy Preview for disscount canceled.

Name Link
🔨 Latest commit b2824de
🔍 Latest deploy log https://app.netlify.com/projects/disscount/deploys/6a76324e4bfeae0008ce51b7

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@OffCrazyFreak, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 48 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bd4dbb12-551f-4ab1-91b9-a405aa88baa1

📥 Commits

Reviewing files that changed from the base of the PR and between 3af9090 and b2824de.

📒 Files selected for processing (4)
  • .claude/skills/multi-tool-code-review/SKILL.md
  • docs/SHARING.md
  • frontend/src/app/(user)/shopping-lists/hooks/use-copy-list-modal.ts
  • frontend/src/app/products/hooks/use-watchlist-item-form.ts

Summary by CodeRabbit

  • New Features

    • Shopping-list copying now lets you enter and edit a custom title.
    • Copy titles are prefilled, validated, and safely truncated when needed.
    • Shared title fields provide consistent labels, placeholders, validation, and autofocus across shopping-list forms.
    • Copy options now have larger, clearer icons and checkboxes.
  • Bug Fixes

    • Improved form validation after prefilled values, ensuring submissions enable correctly.
    • Shopping-list titles are trimmed before validation and submission.
    • Switching between lists now refreshes the copy dialog correctly.
  • Documentation

    • Updated guidance for form validation, copy naming, and review cleanup.

Walkthrough

The PR adds a reusable shopping-list title field, configurable copy names, schema-based title validation, and direct watchlist validity checks. It also adds modal remounting and documents form-prefill behavior and review-cycle cleanup rules.

Changes

Shopping-list form flows

Layer / File(s) Summary
Shared title field and title validation
frontend/src/app/(user)/shopping-lists/components/forms/shopping-list-title-field.tsx, frontend/src/lib/api/schemas/shopping-list.ts, frontend/src/app/(user)/shopping-lists/components/forms/shopping-list-modal.tsx
Shopping-list forms use a shared title field. Request schemas trim titles before applying length checks.
Copy-list form flow
frontend/src/app/(user)/shopping-lists/hooks/use-copy-list-modal.ts, frontend/src/app/(user)/shopping-lists/components/forms/copy-list-modal.tsx, frontend/src/components/custom/modal-router/entity-modal-outlet.tsx, frontend/src/app/(user)/shopping-lists/components/forms/copy-option-row.tsx, docs/SHARING.md
The copy modal validates submitted title data, pre-fills a Unicode-safe suggested title, submits user-provided data, and resets when the selected list changes.

Watchlist validation

Layer / File(s) Summary
Direct watchlist validity
frontend/src/app/products/hooks/use-watchlist-item-form.ts, frontend/src/app/products/components/forms/watchlist-item-modal.tsx, docs/STATE-PERSISTENCE.md
The watchlist hook exposes isFormValid from direct schema parsing. The modal uses it after prefill resets, and the persistence guidance documents stale form state.

Review cycle cleanup

Layer / File(s) Summary
Post-cycle cleanup procedure
.claude/skills/multi-tool-code-review/SKILL.md
The review procedure requires approval before deleting cycle-created artifacts, branches, remotes, or worktrees and reports retained resources.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CopyListModal
  participant useCopyListModal
  participant shoppingListRequestSchema
  CopyListModal->>useCopyListModal: Submit title and copy options
  useCopyListModal->>shoppingListRequestSchema: Validate ShoppingListRequest
  shoppingListRequestSchema-->>useCopyListModal: Return validated data
  useCopyListModal->>useCopyListModal: Call copyList(data)
Loading

Possibly related PRs

Poem

A rabbit fills a title field bright,
Then trims the spaces left and right.
A copied list hops safely through,
Watchlist forms check values too.
Cleanup waits for approval’s cue.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately identifies major changes to sharing, list copying, and product action clusters.
Description check ✅ Passed The description clearly summarizes the release changes across sharing, copying, products, watchlists, and UI accessibility.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 docstrings
  • Create stacked PR
  • Commit on current branch

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: 4

🤖 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 @.claude/skills/multi-tool-code-review/SKILL.md:
- Line 110: Update the branch-deletion safety rule in the multi-tool review
guidance to protect any branch associated with an open PR, not only branches
described as behind one. Require failed PR checks or missing upstream references
to be treated as protected states, and preserve the existing unpushed-commit
check before deletion.
- Around line 96-108: Update the review-run workflow to record exact paths and
refs for every worktree, branch, and remote branch created by the current cycle
in an ownership manifest. Use that manifest, rather than broad discovery results
from git worktree list, git branch --merged, or git ls-remote, to build cleanup
proposals; retain unknown-ownership resources and explicitly report them as
excluded.

In `@frontend/src/app/`(user)/shopping-lists/hooks/use-copy-list-modal.ts:
- Around line 42-45: Update suggestCopyTitle in
frontend/src/app/(user)/shopping-lists/hooks/use-copy-list-modal.ts:42-45 to
limit the generated prefix by JavaScript string length so prefix.length plus
COPY_SUFFIX.length does not exceed TITLE_MAX_LENGTH, while truncating only at
whole code points. The sibling reference in docs/SHARING.md:164-169 requires no
direct change; it is another affected site covered by the title-generation fix.

In `@frontend/src/app/products/hooks/use-watchlist-item-form.ts`:
- Around line 163-173: The comments around the form reset and isFormValid logic
contradict each other about whether reset refreshes validation. Update the stale
reset-validity comment near the watchlist form initialization to state that
reset updates values but does not re-run the resolver unless validation is
explicitly triggered, while preserving the existing schema safeParse validity
calculation and resolver behavior.
🪄 Autofix

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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2d1b7a8a-1815-4ed0-a467-2a3a3f4831b3

📥 Commits

Reviewing files that changed from the base of the PR and between d04e5a2 and 3af9090.

📒 Files selected for processing (12)
  • .claude/skills/multi-tool-code-review/SKILL.md
  • docs/SHARING.md
  • docs/STATE-PERSISTENCE.md
  • frontend/src/app/(user)/shopping-lists/components/forms/copy-list-modal.tsx
  • frontend/src/app/(user)/shopping-lists/components/forms/copy-option-row.tsx
  • frontend/src/app/(user)/shopping-lists/components/forms/shopping-list-modal.tsx
  • frontend/src/app/(user)/shopping-lists/components/forms/shopping-list-title-field.tsx
  • frontend/src/app/(user)/shopping-lists/hooks/use-copy-list-modal.ts
  • frontend/src/app/products/components/forms/watchlist-item-modal.tsx
  • frontend/src/app/products/hooks/use-watchlist-item-form.ts
  • frontend/src/components/custom/modal-router/entity-modal-outlet.tsx
  • frontend/src/lib/api/schemas/shopping-list.ts

Comment thread .claude/skills/multi-tool-code-review/SKILL.md
Comment thread .claude/skills/multi-tool-code-review/SKILL.md Outdated
Comment thread frontend/src/app/(user)/shopping-lists/hooks/use-copy-list-modal.ts Outdated
Comment thread frontend/src/app/products/hooks/use-watchlist-item-form.ts
Changes:
- Build the shortened title a code point at a time, stopping on the UTF-16 length the schema measures
- Correct the matching note in SHARING.md

zod's max() counts UTF-16 code units, so slicing to 91 code points let an emoji title prefill at up to 182 units and open the modal on a validation error the user did not cause. Whole code points are still taken, so the cut cannot split an emoji.

Notes:
- Found by CodeRabbit on #161.
…alid

Changes:
- Parse shoppingListRequestSchema for the copy modal's validity, reading the title through useWatch
- Correct the watchlist form's reset comment, which claimed reset refreshes isValid
- Scope the review skill's cleanup proposal to a manifest of what the cycle created, and protect branches on either side of an open PR

formState.isValid only refreshes when the resolver runs, and a seeding reset does not run it, which docs/STATE-PERSISTENCE.md already records for the watchlist form. The copy modal gated its submit button on that flag, so an untouched valid prefill would have left Kopiraj dead until the user typed. useWatch rather than form.watch, since watch() opts the hook out of the React Compiler.

Notes:
- The skill changes are CodeRabbit findings on #161: branch discovery matched unrelated worktrees and branches by shape alone, and "behind an open PR" missed a branch that is the PR's head.
@OffCrazyFreak
OffCrazyFreak merged commit 7ac5041 into main Aug 7, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant