The frontend component of PuffPastry, meant to interface with the backend, which in turn interfaces with the smart contract.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 

9.3 KiB

sessionId
session-261005-172001-12ux

Requirements

Overview & Goals

The objective is to maximize user engagement and utility by introducing an inline “Add Comment” area within ProposalDetail.vue. By enabling direct inline commenting without modal disruptions, users can effortlessly discuss and provide feedback on governance proposals, reducing interaction friction and streamlining the feedback loop.

Scope

  • In Scope:
    • Embedding an inline comment input area (textarea and action controls) directly inside the Comments section of src/components/ProposalDetail.vue.
    • Integrating CommentService.addComment from src/generated/typescript/services/CommentService.ts to submit comments.
    • Form validation (preventing empty/whitespace submissions) and loading/error states.
    • Refreshing or updating the comment stream upon successful submission.
    • Accessible styling consistent with Tailwind CSS guidelines and the existing proposal layout.
  • Out of Scope:
    • Modal-based comment workflows (explicitly avoided per task specification).
    • Editing, deleting, or nesting/threading multi-level comments in this phase.
    • Backend schema or API endpoint modifications.

User Stories

  • As a stakeholder, I want to post feedback directly beneath a proposal so that I can contribute to the discussion with minimal friction and no context-switching modals.
  • As a user, I want visual feedback while my comment is being submitted (e.g., loading state, error alert on failure) so that I know the exact status of my action.
  • As a keyboard user, I want full keyboard accessibility (tab navigation, clear focus states) so that I can participate efficiently without relying solely on mouse input.

Functional Requirements

  • Inline Input Form:
    • A clean, expandable textarea with placeholder text (e.g., “Add to the discussion...") rendered directly within the <section aria-labelledby="comments-heading"> block.
    • An “Add Comment” (or “Post Comment”) submit button and optional “Cancel” / “Clear” button.
  • Validation & Form State:
    • Disable the submit button when the textarea is empty, whitespace-only, or while a submission is in flight.
    • Display clear error messaging if the network or API call fails.
  • API Dispatch:
    • Construct an AddCommentRequest with proposalId, content, and active/fallback userId.
    • Invoke CommentService.addComment(requestBody).
    • On success, reset the input field and update the comment list so the new comment appears immediately.

Non-Functional Requirements

  • Usability & Utility: Minimal layout shift; smooth transition between idle, submitting, and submitted states.
  • Design Consistency: Match the Tailwind CSS design language (slate borders, amber accents, clear typography) of ProposalDetail.vue and NewAmendmentModal.vue.
  • Accessibility: Semantic HTML <form>, <textarea>, <button>, <label> with associated ARIA attributes for screen readers.

Technical Design

Current Implementation

  • src/components/ProposalDetail.vue: Renders proposal details, amendments via AmendmentCarousel.vue, and voting cards. The comments section currently contains static markup with a hidden placeholder (v-if="false").
  • src/generated/typescript/services/CommentService.ts: Exports CommentService with:
    • addComment(requestBody: AddCommentRequest): CancelablePromise<SelectableComment> (POST /api/v1/comment/add)
    • listComments(proposalId: number): CancelablePromise<Array<CommentWithUser>> (GET /api/v1/comments/list)
  • src/generated/typescript/models/AddCommentRequest.ts: Defines { content: string; proposalId: number; userId: number; }.
  • src/generated/typescript/models/CommentWithUser.ts: Defines comment shape with author metadata (id, content, createdAt, username, fullName, userId, proposalId).

Key Decisions

  1. Inline Placement in ProposalDetail.vue:
    • Approach: Integrate the comment box directly below the comments header in ProposalDetail.vue instead of launching a modal.
    • Rationale: Maximizes utility and minimizes UX friction by keeping the proposal text in view while writing feedback.
  2. Dynamic Comments Fetch & Immediate Refresh:
    • Approach: Load comments for proposal.id via CommentService.listComments and refresh/append on new comment creation.
    • Rationale: Provides immediate confirmation to the user that their contribution was recorded without necessitating a full page reload.
  3. Robust Input Validation & Loading States:
    • Approach: Use reactive refs (commentText, isSubmitting, errorMessage) to gate form submission and provide actionable feedback.
    • Rationale: Prevents accidental duplicate requests and ensures users are informed of network or validation issues.

Proposed Changes

  • src/components/ProposalDetail.vue:
    • Import CommentService, AddCommentRequest, and CommentWithUser from ../generated/typescript.
    • Add reactive state: newComment, isSubmitting, submitError, comments, and loadingComments.
    • Implement fetchComments(proposalId) on onMounted and on watch(proposalId).
    • Implement handleAddComment() to call CommentService.addComment and reset the form.
    • Replace placeholder section with the inline comment submission form and existing comments list.

Data Models / Contracts

// Payload sent to CommentService.addComment
const requestBody: AddCommentRequest = {
  proposalId: props.proposal.id,
  content: commentText.value.trim(),
  userId: activeUserId ?? 1, // Fallback/resolved user ID
};

Architecture Diagram

graph TD
  User[User] -->|Types comment & clicks Submit| CommentForm[Inline Comment Area in ProposalDetail]
  CommentForm -->|addComment| CommentService[CommentService.addComment]
  CommentService -->|POST /api/v1/comment/add| BackendAPI[Backend API]
  BackendAPI -->|SelectableComment| CommentService
  CommentService -->|Success / New Comment| StateUpdate[Update Local Comments State & Reset Form]
  StateUpdate -->|Re-render| UI[Updated Discussion Stream]

File Structure

  • src/components/ProposalDetail.vue (Modified): Inline form, reactive state, and CommentService integration.
  • src/generated/typescript/services/CommentService.ts (Referenced): Backend API client for comment actions.

Risks & Mitigations

  • Network Failure or 400/500 Errors: Capture API errors in a dedicated errorMessage ref and display an inline alert without losing user input.
  • Double Submissions: Disable the submit button immediately when isSubmitting is true.

Testing

Validation Approach

Verification focuses on maximizing automated and interactive confidence across normal, boundary, and error conditions.

Key Scenarios

  1. Inline Form Rendering:
    • Verify textarea and “Add Comment” button render cleanly within the comments section of ProposalDetail.vue.
    • Verify placeholder text and accessible labels are present.
  2. Comment Submission Flow:
    • Enter valid comment text and submit.
    • Verify CommentService.addComment is invoked with { proposalId, content, userId }.
    • Verify textarea is cleared upon successful submission and the discussion stream updates.
  3. Empty Input Prevention:
    • Ensure the submit button is disabled when the textarea is empty or contains only whitespace.
  4. Loading & Disabled States:
    • Verify the submit button reflects pending state and prevents concurrent submissions.

Edge Cases

  • API Error / Server Failure: Verify that error messages are displayed prominently inline without clearing the user’s drafted text.
  • Proposal ID Changes: Verify comments state is reset and re-fetched when switching between proposals.
  • Special Characters & Multiline Text: Verify formatting and line breaks in comments are preserved.

Delivery Steps

✓ Step 1: Create inline comment form UI and state management

Build the inline comment form UI within the Comments section of ProposalDetail.vue.

  • Add reactive state variables for comment content (commentText), submission loading state (isSubmitting), error messages (commentError), and comments list (comments, isLoadingComments).
  • Insert an inline form in the comments section with a styled <textarea> input, accessible labels, character/input guidance, and action controls (submit and cancel/reset buttons).
  • Implement input validation so that empty or whitespace-only submissions are disabled.
  • Add comment list rendering within the comments section using CommentService.listComments(proposal.id) on mount and when proposal changes, providing immediate visual feedback for existing discussions.

✓ Step 2: Integrate CommentService API submission and discussion refresh

Connect the inline form to CommentService.addComment to persist user comments and refresh the discussion stream.

  • Implement the submitComment async handler calling CommentService.addComment({ proposalId: proposal.id, content: commentText.value.trim(), userId }).
  • Include robust error handling to display user-friendly inline error alerts if the API request fails.
  • Clear the input textarea upon successful comment submission.
  • Re-fetch or append the new comment into the local comments list so users immediately see their contribution without a full page reload.
  • Verify type checks and build via vue-tsc -b to guarantee seamless integration and zero regressions.