Skip to content

feat: 019 — PigDetail card redesign - #21

Merged
archae0pteryx merged 1 commit into
mainfrom
feat/019-pig-detail-redesign
May 3, 2026
Merged

feat: 019 — PigDetail card redesign#21
archae0pteryx merged 1 commit into
mainfrom
feat/019-pig-detail-redesign

Conversation

@archae0pteryx

@archae0pteryx archae0pteryx commented May 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds onAddTask(text) prop to PigDetail; Enter appends task via focusWriter.appendTask and clears field
  • Card background fully opaque (rgba(20,20,20,1))
  • min-width: 340px, padding: 16px, task list max-height: 240px with scroll
  • CARD_W constant updated to 340 to keep card-position clamping in sync

Test plan

  • PigDetail.test.tsx: renders input, Enter calls onAddTask, clears field, empty text blocked, Escape still closes
  • App.test.tsx: add-task routes to focusWriter.appendTask with correct focus id
  • task check green
  • Card visually opaque, wider, task list scrolls when long

Closes #17

Summary by CodeRabbit

  • New Features

    • Added an input field in the detail view that allows users to add new tasks directly from within the task details. Tasks can be submitted by pressing Enter.
  • Tests

    • Added test coverage for the new task input functionality.
  • Chores

    • Updated development dependencies to support enhanced testing capabilities.

Add onAddTask prop; Enter appends task via focusWriter.appendTask and
clears the field. Card background fully opaque, min-width 340px,
padding 16px, task list scrolls at max-height 240px.
@coderabbitai

coderabbitai Bot commented May 3, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds an inline task-creation input to the PigDetail card component. It includes the new @testing-library/user-event dependency, wires a handleAddTask callback from App through to PigDetail, increases the card width to 340px, styles the new input, and adds comprehensive test coverage for the feature.

Changes

Task Input Implementation

Layer / File(s) Summary
Dependency
package.json
Added @testing-library/user-event ^14.6.1 to devDependencies for interactive test simulation.
Props & State
src/components/PigDetail.tsx
PigDetailProps now includes onAddTask(text: string) callback; component manages taskInput state via useState.
Component Layout
src/components/PigDetail.tsx
Card width increased from 210 to 340px; a controlled input field added after the task list with Enter-key submission behavior.
Handler Wiring
src/components/App.tsx
New handleAddTask async handler calls focusWriter.appendTask(selectedFocus.id, text) and silently handles errors; passed as onAddTask prop to PigDetail.
Styling
src/styles.css
.pig-detail background opacity and padding adjusted; .pig-detail-tasks gains max-height: 240px with overflow-y: auto for scrolling; new .pig-detail-add-task input styles (base, placeholder, focus states).
Tests
src/components/App.test.tsx, src/components/PigDetail.test.tsx
End-to-end test verifies clicking a pig and submitting a task; unit tests cover input placeholder, Enter/Escape behavior, text trimming, and whitespace rejection.

Sequence Diagram

sequenceDiagram
    actor User
    participant App
    participant PigDetail
    participant focusWriter

    User->>App: Click "Customer X bug" pig
    App->>PigDetail: Render with onAddTask callback
    User->>PigDetail: Type "write tests" in Add task input
    User->>PigDetail: Press Enter
    PigDetail->>App: Call onAddTask("write tests")
    App->>focusWriter: appendTask(selectedFocus.id, "write tests")
    focusWriter-->>App: Task appended
    App-->>PigDetail: Handler completes
    PigDetail->>PigDetail: Clear input field
    PigDetail-->>User: Input cleared, ready for next task
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A card grows wide and input gleams,
Tasks added swift, no API schemes,
The pig detail card now holds the way,
Type and Enter, tasks append and stay!
hop 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: 019 — PigDetail card redesign' accurately describes the main change: the redesign of the PigDetail card component with new features like task input, opacity changes, and layout adjustments.
Linked Issues check ✅ Passed All key requirements from issue #17 are met: onAddTask callback added to PigDetail [PigDetail.tsx], handleAddTask implemented in App [App.tsx], card background made opaque [styles.css], card width increased to 340px [PigDetail.tsx], padding adjusted [styles.css], task list max-height with scroll added [styles.css], tests added [PigDetail.test.tsx, App.test.tsx].
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #17 objectives: package.json dependency addition supports the testing, component changes implement the task input feature and styling requirements, and new tests verify the implementation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/019-pig-detail-redesign

Review rate limit: 8/10 reviews remaining, refill in 11 minutes and 56 seconds.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/PigDetail.tsx (1)

40-40: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Clamp card X position to a left boundary.

At Line 40, Math.min(...) alone can yield a negative X on narrow viewports, making the card partially off-screen and hard to close/interact with.

Proposed fix
-  const x = Math.min(rawX, viewportW - CARD_W - 16);
+  const x = Math.max(16, Math.min(rawX, viewportW - CARD_W - 16));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/PigDetail.tsx` at line 40, The computed card X uses Math.min
only (const x = Math.min(rawX, viewportW - CARD_W - 16)) which can go negative;
update the clamp in the PigDetail component so x is bounded on both sides by
taking the max of the left padding and the current min value (use left boundary
16 and right boundary viewportW - CARD_W - 16 referencing rawX and CARD_W) to
ensure the card never renders off-screen.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/App.tsx`:
- Around line 34-41: The App component currently performs direct I/O in
handleAddTask by calling focusWriter.appendTask(selectedFocus.id, text); extract
that persistence logic into a non-UI layer (e.g., create a task service or hook
like useTaskService or TaskController with a method appendTask(focusId: string,
text: string) that handles errors/logging) and replace the in-component call
with a UI-safe callback (e.g., call addTask(text) or useAddTask(text) from the
service/hook). Ensure the new service API accepts a focusId (so App only passes
selectedFocus.id or a selectedFocusChanged callback) and remove any direct I/O
from App.handleAddTask and other occurrences (also update the similar call
around line 65) so App becomes view-only and consumes the service's callback.

In `@src/components/PigDetail.tsx`:
- Around line 29-30: In PigDetail, task draft text persists across focus
switches: add logic to reset taskInput by calling setTaskInput("") whenever the
selected focus changes (watch the prop/state that represents the current focus,
e.g., selectedFocus or selectedFocusId) — implement this with a useEffect inside
the PigDetail component that depends on that selected-focus identifier so
taskInput is cleared on focus switch (also ensure any submit/close handlers
around the existing task creation flow that reference taskInput/ setTaskInput
follow the same reset behavior).

---

Outside diff comments:
In `@src/components/PigDetail.tsx`:
- Line 40: The computed card X uses Math.min only (const x = Math.min(rawX,
viewportW - CARD_W - 16)) which can go negative; update the clamp in the
PigDetail component so x is bounded on both sides by taking the max of the left
padding and the current min value (use left boundary 16 and right boundary
viewportW - CARD_W - 16 referencing rawX and CARD_W) to ensure the card never
renders off-screen.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3be9c248-62d4-41fb-8f8c-fb84386497cd

📥 Commits

Reviewing files that changed from the base of the PR and between 9d896cf and abc4555.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (6)
  • package.json
  • src/components/App.test.tsx
  • src/components/App.tsx
  • src/components/PigDetail.test.tsx
  • src/components/PigDetail.tsx
  • src/styles.css

Comment thread src/components/App.tsx
Comment on lines +34 to +41
async function handleAddTask(text: string) {
if (!selectedFocus) return;
try {
await focusWriter.appendTask(selectedFocus.id, text);
} catch {
// focusWriter already logs the typed error
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

Move add-task persistence out of the component layer.

At Line 37, App performs direct I/O via focusWriter.appendTask(...). This violates the component-layer boundary and should be delegated to a non-UI layer (e.g., hook/controller/service), with App consuming a UI-safe callback.

As per coding guidelines, src/components/**/*.{ts,tsx}: Frontend React components in src/components/ should be view-only with no fetch and no direct I/O.

Also applies to: 65-65

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/App.tsx` around lines 34 - 41, The App component currently
performs direct I/O in handleAddTask by calling
focusWriter.appendTask(selectedFocus.id, text); extract that persistence logic
into a non-UI layer (e.g., create a task service or hook like useTaskService or
TaskController with a method appendTask(focusId: string, text: string) that
handles errors/logging) and replace the in-component call with a UI-safe
callback (e.g., call addTask(text) or useAddTask(text) from the service/hook).
Ensure the new service API accepts a focusId (so App only passes
selectedFocus.id or a selectedFocusChanged callback) and remove any direct I/O
from App.handleAddTask and other occurrences (also update the similar call
around line 65) so App becomes view-only and consumes the service's callback.

Comment on lines +29 to +30
const [taskInput, setTaskInput] = useState("");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Reset draft input when the selected focus changes.

taskInput persists across focus switches because local state is reused. This leaks draft text between cards.

Proposed fix
   const [taskInput, setTaskInput] = useState("");
+
+  useEffect(() => {
+    setTaskInput("");
+  }, [focus.id]);

Also applies to: 74-85

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/PigDetail.tsx` around lines 29 - 30, In PigDetail, task draft
text persists across focus switches: add logic to reset taskInput by calling
setTaskInput("") whenever the selected focus changes (watch the prop/state that
represents the current focus, e.g., selectedFocus or selectedFocusId) —
implement this with a useEffect inside the PigDetail component that depends on
that selected-focus identifier so taskInput is cleared on focus switch (also
ensure any submit/close handlers around the existing task creation flow that
reference taskInput/ setTaskInput follow the same reset behavior).

@archae0pteryx
archae0pteryx merged commit 8685ad6 into main May 3, 2026
2 checks passed
@archae0pteryx
archae0pteryx deleted the feat/019-pig-detail-redesign branch May 3, 2026 15:37
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.

019 — PigDetail card redesign: editable, opaque, larger

1 participant