Skip to content

ENG-2877: Update Slack integration for privacy assessments#7584

Merged
kruulik merged 5 commits intomainfrom
2877-slack
Mar 6, 2026
Merged

ENG-2877: Update Slack integration for privacy assessments#7584
kruulik merged 5 commits intomainfrom
2877-slack

Conversation

@kruulik
Copy link
Copy Markdown
Contributor

@kruulik kruulik commented Mar 6, 2026

Ticket ENG-2877

Description Of Changes

Enhance the privacy assessment detail page Slack integration by replacing the modal-based input request flow with a direct button action, adding real-time polling for new answers, and showing toast notifications when Slack responses arrive.

  • Replace RequestInputModal with direct "Request input from team" button that sends questions with NEEDS_INPUT status to the configured Slack channel
  • Add 15-second polling for assessment updates when a questionnaire has been sent and the assessment is incomplete
  • Show success notification when new Slack answers are detected via polling
  • Update answer source labels: "Team input" → "Via Slack", "User input" → "Manual input"
  • Temporary fix to ensure all assessments are generated (not just high-risk)

Code Changes

  • clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx - Replace modal flow with direct Slack send, add polling and new-answer notifications
  • clients/admin-ui/src/features/privacy-assessments/constants.ts - Update answer source display labels
  • clients/admin-ui/src/features/privacy-assessments/privacy-assessments.slice.ts - Add high_risk_only: false default to assessment creation

Steps to Confirm

  1. Navigate to a privacy assessment detail page
  2. Click "Request input from team" — questions should be sent to the configured Slack channel
  3. Wait for Slack responses — a "New answer from Slack" notification should appear
  4. Verify answer source labels show "Via Slack" for Slack-sourced answers and "Manual input" for user-entered answers

Pre-Merge Checklist

  • Issue requirements met
  • All CI pipelines succeeded
  • CHANGELOG.md updated
    • Updates unreleased work already in Changelog, no new entry necessary
  • UX feedback:
    • No UX review needed
  • Followup issues:
    • No followup issues
  • Database migrations:
    • No migrations
  • Documentation:
    • No documentation updates required

Summary by CodeRabbit

  • New Features

    • Send privacy assessment questionnaires directly to Slack channels with loading indicators and success/error feedback.
    • Real-time polling to detect new Slack responses and show toast notifications when teammates submit answers.
    • Request flow now uses a direct send action instead of a modal.
  • Changed

    • UI labels updated to distinguish manual input from Slack-sourced responses.
    • Assessments now include non‑high‑risk items by default (high_risk_only = false).

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
fides-plus-nightly Ready Ready Preview, Comment Mar 6, 2026 2:42pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
fides-privacy-center Ignored Ignored Mar 6, 2026 2:42pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 6, 2026

📝 Walkthrough

Walkthrough

Adds Slack questionnaire support to privacy assessments: polling incomplete assessments for Slack-sent questions, detecting new team-sourced answers and showing notifications, sending questionnaires to Slack via a mutation, updates answer-source labels, and sets a default high_risk_only: false on assessment creation.

Changes

Cohort / File(s) Summary
Changelog
changelog/7584-slack-assessment-integration.yaml
Adds changelog entry documenting Slack questionnaire integration.
Assessment Detail (UI)
clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx
Adds polling for assessments when Slack questionnaire was sent and incomplete; tracks team-input question IDs to detect new Slack answers and trigger toast notifications; adds useCreateQuestionnaireMutation flow to send NEEDS_INPUT questions to Slack; integrates notification holder and loading states; removes modal-based request flow.
Constants
clients/admin-ui/src/features/privacy-assessments/constants.ts
Updates ANSWER_SOURCE_LABELS: USER_INPUT -> "Manual input", TEAM_INPUT -> "Via Slack".
Slice / Mutation Default
clients/admin-ui/src/features/privacy-assessments/privacy-assessments.slice.ts
createPrivacyAssessment now ensures request body includes high_risk_only: false by default (wraps provided body).

Sequence Diagram(s)

sequenceDiagram
    participant UI as Assessment Detail UI
    participant Poll as Polling Hook
    participant API as Privacy Assessment API
    participant Notif as Notification System

    rect rgba(100,150,200,0.5)
        Note over UI,Poll: Polling for updates (e.g., every 15s)
        UI->>Poll: subscribe if questionnaire sent & incomplete
        Poll->>API: fetch assessment + answers
        API-->>Poll: return assessment data
        Poll-->>UI: deliver updated data
    end

    rect rgba(100,200,150,0.5)
        Note over UI,Notif: Detect new team-input answers
        UI->>UI: compare previous vs current team-input question IDs
        alt New team-input answer detected
            UI->>Notif: trigger "New answer from Slack" toast
            Notif-->>UI: display notification
        end
    end

    rect rgba(200,150,100,0.5)
        Note over UI,API: Send questionnaire to Slack
        UI->>API: useCreateQuestionnaireMutation (send NEEDS_INPUT questions)
        API-->>UI: success / error
        UI->>UI: show loading state and toast
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

Privacy Assessments

Suggested reviewers

  • lucanovera

Poem

🐰 I hopped through code and Slack tonight,
Polling answers in the pale screen light.
A toast cried “New answer from Slack!” with cheer,
I sent the questions — replies soon appear.
Hop, click, notify — the assessment’s clear.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: updating Slack integration for privacy assessments, which aligns with the core objective of enhancing the Slack integration workflow.
Description check ✅ Passed The description follows the repository template with all major sections completed: ticket reference, clear description of changes, code changes listed, confirmation steps provided, and pre-merge checklist mostly filled out.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 2877-slack

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

@kruulik kruulik changed the title ENG-2877: Enhance Slack integration for privacy assessments ENG-2877: Update Slack integration for privacy assessments Mar 6, 2026
@kruulik kruulik marked this pull request as ready for review March 6, 2026 14:10
@kruulik kruulik requested a review from a team as a code owner March 6, 2026 14:10
@kruulik kruulik requested review from jpople and removed request for a team March 6, 2026 14:10
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 6, 2026

Greptile Summary

This PR replaces the modal-based Slack questionnaire flow in the privacy assessment detail page with a direct button action, adds 15-second polling for new answers, and shows toast notifications when Slack responses arrive. It also updates answer source labels and applies a temporary high_risk_only: false default to assessment creation.

Key issues:

  • Regression: EvidenceDrawer is now gated behind slackChannelName, preventing users without Slack configured from accessing the evidence drawer — a feature entirely unrelated to Slack and previously unconditional.
  • Polling interval too aggressive: POLL_INTERVAL = 15_000 (15 seconds) is a development-level value; production polling intervals should be in hours, not seconds.
  • Dead code left in place: The isRequestInputOpen state variable and entire RequestInputModal JSX block are commented out with "does not fit demo needs at the moment"; this should be fully removed.
  • Untracked technical debt: The high_risk_only: false "temporary fix" has no linked follow-up issue, creating risk that it will persist indefinitely.

Confidence Score: 2/5

  • Not safe to merge — contains a functional regression (EvidenceDrawer hidden from users without Slack) and production-readiness issues (15-second polling interval).
  • The PR introduces a critical regression where evidence viewing (an unrelated feature) becomes inaccessible when no Slack channel is configured. Combined with a 15-second polling interval that violates production guidelines, a dangling TODO in commented-out code, and untracked technical debt, the PR requires fixes before merging. The AssessmentDetail.tsx component is the core of these issues.
  • clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx (move EvidenceDrawer outside slackChannelName gate, increase polling interval to production-appropriate value, remove dead code) and clients/admin-ui/src/features/privacy-assessments/privacy-assessments.slice.ts (link temporary fix to follow-up issue).

Last reviewed commit: 46d3c04

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx (1)

321-328: Consider removing commented-out code or creating a tracking issue.

Commented-out code tends to become stale and confusing over time. If RequestInputModal is no longer needed for the new flow, consider removing it entirely. If it may be needed later, create a tracking issue and remove the code—version control preserves it.

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

In `@clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx`
around lines 321 - 328, Remove the commented-out RequestInputModal block in
AssessmentDetail (the JSX referencing RequestInputModal, isRequestInputOpen,
setIsRequestInputOpen, assessment.id, allQuestions, slackChannelName) or if it
may be needed later open a tracking issue (with rationale and where it lives)
and then remove the commented code so the component stays clean; ensure any
necessary behavior is documented in the issue and rely on VCS to restore the
snippet if required.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx`:
- Around line 321-328: Remove the commented-out RequestInputModal block in
AssessmentDetail (the JSX referencing RequestInputModal, isRequestInputOpen,
setIsRequestInputOpen, assessment.id, allQuestions, slackChannelName) or if it
may be needed later open a tracking issue (with rationale and where it lives)
and then remove the commented code so the component stays clean; ensure any
necessary behavior is documented in the issue and rely on VCS to restore the
snippet if required.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cea22ba3-fd92-42d9-ae61-c8ade4472d82

📥 Commits

Reviewing files that changed from the base of the PR and between 8f2e7e4 and 46d3c04.

📒 Files selected for processing (4)
  • changelog/7584-slack-assessment-integration.yaml
  • clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx
  • clients/admin-ui/src/features/privacy-assessments/constants.ts
  • clients/admin-ui/src/features/privacy-assessments/privacy-assessments.slice.ts

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

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)
clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx (1)

319-329: Consider removing or tracking the commented-out modal code.

Commented-out code adds noise and can become stale. If the RequestInputModal might be restored later, consider tracking it in an issue rather than keeping it commented in the codebase. If it's truly obsolete, removing it would clean up the file.

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

In `@clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx`
around lines 319 - 329, Remove the commented-out RequestInputModal block to
clean up the file or, if you intend to restore it later, delete the commented
code and create a tracking issue referencing this UI piece (RequestInputModal
and the related state variables isRequestInputOpen / setIsRequestInputOpen and
props assessment.id, allQuestions, slackChannelName); alternatively move the
modal behind a feature flag or feature branch if you want it preserved in code
but inactive. Ensure any removed references (isRequestInputOpen,
setIsRequestInputOpen) are also cleaned up if they become unused.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx`:
- Around line 155-181: handleRequestInput can call createQuestionnaire with an
empty include_question_ids array when there are no NEEDS_INPUT questions; add a
defensive guard in handleRequestInput to compute needsInputIds (from
allQuestions.filter...map...) and return early (and show a user-friendly
warning) if needsInputIds.length === 0 so the API is never called with an empty
array, and also update the button enable/disable logic (currently using
isComplete/pendingAnswers) to base visibility/disabled state on the presence of
NEEDS_INPUT questions (i.e., the same filter used to compute needsInputIds) so
UI and action are consistent; reference symbols: handleRequestInput,
needsInputIds, allQuestions, AnswerStatus.NEEDS_INPUT, isComplete,
pendingAnswers, createQuestionnaire, include_question_ids.

---

Nitpick comments:
In `@clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx`:
- Around line 319-329: Remove the commented-out RequestInputModal block to clean
up the file or, if you intend to restore it later, delete the commented code and
create a tracking issue referencing this UI piece (RequestInputModal and the
related state variables isRequestInputOpen / setIsRequestInputOpen and props
assessment.id, allQuestions, slackChannelName); alternatively move the modal
behind a feature flag or feature branch if you want it preserved in code but
inactive. Ensure any removed references (isRequestInputOpen,
setIsRequestInputOpen) are also cleaned up if they become unused.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d94db060-6f9f-4310-9729-d5c6b17f8fb0

📥 Commits

Reviewing files that changed from the base of the PR and between 46d3c04 and 317ee0d.

📒 Files selected for processing (1)
  • clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx

Comment on lines +155 to +181
const handleRequestInput = async () => {
if (!slackChannelName) {
return;
}

const needsInputIds = allQuestions
.filter((q) => q.answer_status === AnswerStatus.NEEDS_INPUT)
.map((q) => q.question_id);

try {
await createQuestionnaire({
id: assessment.id,
body: {
channel: slackChannelName,
include_question_ids: needsInputIds,
},
}).unwrap();
message.success(`Questions sent to ${slackChannelName} on Slack.`);
} catch (error) {
message.error(
getErrorMessage(
error as RTKErrorResult["error"],
"Failed to send questionnaire. Please try again.",
),
);
}
};
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

The empty questionnaire scenario is theoretically possible but requires specific conditions.

The current implementation has a logical issue: isComplete is true when there are no questions with NEEDS_INPUT status AND no answer text (pendingAnswers.length === 0 at line 75). However, handleRequestInput sends all questions with NEEDS_INPUT status regardless of whether they have answer text. If all NEEDS_INPUT questions happen to have answer text, the button would be disabled (isComplete = true) but needsInputIds could potentially be empty depending on the question lifecycle.

Adding the guard clause is good defensive programming, especially since there's no API-level validation visible in the codebase to prevent empty include_question_ids arrays. However, consider also reviewing whether the button visibility logic should be based on whether any NEEDS_INPUT questions exist, rather than on pendingAnswers (questions without both status AND text).

Proposed fix
 const handleRequestInput = async () => {
   if (!slackChannelName) {
     return;
   }

   const needsInputIds = allQuestions
     .filter((q) => q.answer_status === AnswerStatus.NEEDS_INPUT)
     .map((q) => q.question_id);

+  if (needsInputIds.length === 0) {
+    message.info("No questions currently need input.");
+    return;
+  }
+
   try {
     await createQuestionnaire({
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleRequestInput = async () => {
if (!slackChannelName) {
return;
}
const needsInputIds = allQuestions
.filter((q) => q.answer_status === AnswerStatus.NEEDS_INPUT)
.map((q) => q.question_id);
try {
await createQuestionnaire({
id: assessment.id,
body: {
channel: slackChannelName,
include_question_ids: needsInputIds,
},
}).unwrap();
message.success(`Questions sent to ${slackChannelName} on Slack.`);
} catch (error) {
message.error(
getErrorMessage(
error as RTKErrorResult["error"],
"Failed to send questionnaire. Please try again.",
),
);
}
};
const handleRequestInput = async () => {
if (!slackChannelName) {
return;
}
const needsInputIds = allQuestions
.filter((q) => q.answer_status === AnswerStatus.NEEDS_INPUT)
.map((q) => q.question_id);
if (needsInputIds.length === 0) {
message.info("No questions currently need input.");
return;
}
try {
await createQuestionnaire({
id: assessment.id,
body: {
channel: slackChannelName,
include_question_ids: needsInputIds,
},
}).unwrap();
message.success(`Questions sent to ${slackChannelName} on Slack.`);
} catch (error) {
message.error(
getErrorMessage(
error as RTKErrorResult["error"],
"Failed to send questionnaire. Please try again.",
),
);
}
};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx`
around lines 155 - 181, handleRequestInput can call createQuestionnaire with an
empty include_question_ids array when there are no NEEDS_INPUT questions; add a
defensive guard in handleRequestInput to compute needsInputIds (from
allQuestions.filter...map...) and return early (and show a user-friendly
warning) if needsInputIds.length === 0 so the API is never called with an empty
array, and also update the button enable/disable logic (currently using
isComplete/pendingAnswers) to base visibility/disabled state on the presence of
NEEDS_INPUT questions (i.e., the same filter used to compute needsInputIds) so
UI and action are consistent; reference symbols: handleRequestInput,
needsInputIds, allQuestions, AnswerStatus.NEEDS_INPUT, isComplete,
pendingAnswers, createQuestionnaire, include_question_ids.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx (1)

154-170: ⚠️ Potential issue | 🟠 Major

Guard empty include_question_ids and align button visibility with NEEDS_INPUT.

Line 159-Line 169 can send an empty include_question_ids array, and Line 269 currently gates UI by isComplete instead of whether any question is actually NEEDS_INPUT. This can trigger avoidable API calls and inconsistent UX.

Proposed fix
+  const needsInputIds = useMemo(
+    () =>
+      allQuestions
+        .filter((q) => q.answer_status === AnswerStatus.NEEDS_INPUT)
+        .map((q) => q.question_id),
+    [allQuestions],
+  );
+
   const handleRequestInput = async () => {
     if (!slackChannelName) {
       return;
     }
-
-    const needsInputIds = allQuestions
-      .filter((q) => q.answer_status === AnswerStatus.NEEDS_INPUT)
-      .map((q) => q.question_id);
+    if (needsInputIds.length === 0) {
+      message.info("No questions currently need input.");
+      return;
+    }
 
     try {
       await createQuestionnaire({
         id: assessment.id,
         body: {
           channel: slackChannelName,
           include_question_ids: needsInputIds,
         },
       }).unwrap();
       message.success(`Questions sent to ${slackChannelName} on Slack.`);
@@
-        {!isComplete && (
+        {!isComplete && needsInputIds.length > 0 && (
           <Tooltip

Also applies to: 269-287

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

In `@clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx`
around lines 154 - 170, The request function handleRequestInput should not call
createQuestionnaire when include_question_ids would be an empty array: compute
needsInputIds from allQuestions.filter(q => q.answer_status ===
AnswerStatus.NEEDS_INPUT).map(...), and early-return if needsInputIds.length ===
0 before calling createQuestionnaire (so do not send an empty
include_question_ids). Also change the UI button visibility logic that currently
uses isComplete to instead check whether there exists at least one question with
answer_status === AnswerStatus.NEEDS_INPUT (e.g., use the same
needsInputIds.length > 0 condition) so the button is shown only when input is
actually needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx`:
- Around line 118-125: The teamInputIdsRef Set is only initialized once for the
component lifetime, causing stale baseline when switching assessments
(assessment.id) and leading to incorrect "New answer from Slack" toasts; update
initialization logic so teamInputIdsRef is reset whenever the current assessment
changes: move or add a useEffect that watches assessment.id (or allQuestions)
and reassigns teamInputIdsRef.current = new Set(...) using
allQuestions.filter(...).map(q => q.question_id), and apply the same reset
pattern for the other similar block referenced at lines 127-142 to ensure
baselines are recomputed per assessment.

---

Duplicate comments:
In `@clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx`:
- Around line 154-170: The request function handleRequestInput should not call
createQuestionnaire when include_question_ids would be an empty array: compute
needsInputIds from allQuestions.filter(q => q.answer_status ===
AnswerStatus.NEEDS_INPUT).map(...), and early-return if needsInputIds.length ===
0 before calling createQuestionnaire (so do not send an empty
include_question_ids). Also change the UI button visibility logic that currently
uses isComplete to instead check whether there exists at least one question with
answer_status === AnswerStatus.NEEDS_INPUT (e.g., use the same
needsInputIds.length > 0 condition) so the button is shown only when input is
actually needed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ef093261-a92d-4365-b484-eb4eb8c6fd8b

📥 Commits

Reviewing files that changed from the base of the PR and between 317ee0d and 7043371.

📒 Files selected for processing (1)
  • clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx

Comment on lines +118 to +125
const teamInputIdsRef = useRef<Set<string> | null>(null);
if (teamInputIdsRef.current === null) {
teamInputIdsRef.current = new Set(
allQuestions
.filter((q) => q.answer_source === AnswerSource.TEAM_INPUT)
.map((q) => q.question_id),
);
}
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

Reset team-input baseline when switching assessments.

Line 118-Line 125 initializes teamInputIdsRef only once for the component lifetime. If assessment.id changes without unmounting, Line 136 can emit a false “New answer from Slack” toast on first render of the new assessment.

Proposed fix
-  const teamInputIdsRef = useRef<Set<string> | null>(null);
-  if (teamInputIdsRef.current === null) {
-    teamInputIdsRef.current = new Set(
-      allQuestions
-        .filter((q) => q.answer_source === AnswerSource.TEAM_INPUT)
-        .map((q) => q.question_id),
-    );
-  }
+  const teamInputIdsRef = useRef<Set<string>>(
+    new Set(
+      allQuestions
+        .filter((q) => q.answer_source === AnswerSource.TEAM_INPUT)
+        .map((q) => q.question_id),
+    ),
+  );
+
+  useEffect(() => {
+    teamInputIdsRef.current = new Set(
+      allQuestions
+        .filter((q) => q.answer_source === AnswerSource.TEAM_INPUT)
+        .map((q) => q.question_id),
+    );
+  }, [assessment.id]);
@@
-    const prevIds = teamInputIdsRef.current!;
+    const prevIds = teamInputIdsRef.current;

Also applies to: 127-142

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

In `@clients/admin-ui/src/features/privacy-assessments/AssessmentDetail.tsx`
around lines 118 - 125, The teamInputIdsRef Set is only initialized once for the
component lifetime, causing stale baseline when switching assessments
(assessment.id) and leading to incorrect "New answer from Slack" toasts; update
initialization logic so teamInputIdsRef is reset whenever the current assessment
changes: move or add a useEffect that watches assessment.id (or allQuestions)
and reassigns teamInputIdsRef.current = new Set(...) using
allQuestions.filter(...).map(q => q.question_id), and apply the same reset
pattern for the other similar block referenced at lines 127-142 to ensure
baselines are recomputed per assessment.

Copy link
Copy Markdown
Contributor

@lucanovera lucanovera left a comment

Choose a reason for hiding this comment

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

New UI works great, the polling for new Slack answers is a nice improvement. Approved!

@kruulik kruulik added this pull request to the merge queue Mar 6, 2026
Merged via the queue into main with commit 13d0dcf Mar 6, 2026
47 checks passed
@kruulik kruulik deleted the 2877-slack branch March 6, 2026 15:08
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.

2 participants