The frontend component of PuffPastry, meant to interface with the backend, which in turn interfaces with the smart contract.
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. ---
  2. sessionId: session-261002-164508-dfif
  3. ---
  4. # Requirements
  5. ### Overview & Goals
  6. The objective of this task is to convert the placeholder `Add` element in `AmendmentCarousel.vue` into a fully styled, accessible "dummy" amendment card. Clicking this card launches a new amendment creation modal, allowing users to propose an amendment to the currently viewed proposal using their connected Stellar Freighter wallet.
  7. ### Scope
  8. - **In Scope**:
  9. - Transforming the existing placeholder `<article>` in `src/components/AmendmentCarousel.vue` into an attractive, interactive dummy amendment card.
  10. - Creating `src/components/modals/NewAmendmentModal.vue` to capture amendment details (name/title and markdown content).
  11. - Integrating `AmendmentService.addAmendment` with wallet authorization via `@stellar/freighter-api`.
  12. - Refreshing the amendment list in `AmendmentCarousel.vue` upon successful submission.
  13. - Supporting full keyboard navigation and accessible roles for the dummy amendment trigger.
  14. - **Out of Scope**:
  15. - Modifying backend API endpoints or database schemas (already provided via `AmendmentService`).
  16. - Changing voting or confirm/reject approval flows for amendments.
  17. ### User Stories
  18. - **As a contributor**, I want to click an "Add Amendment" card in the carousel so that I can easily propose a revision to the current proposal.
  19. - **As a keyboard user**, I want to focus and activate the "Add Amendment" card with Enter or Space so that the interface is fully accessible.
  20. - **As a proposer**, I want a clean modal form to enter the amendment title and body and sign with my wallet so that my submission is properly recorded.
  21. ### Functional Requirements
  22. - **Card UI & Styling**: The dummy card must match the carousel dimensions (`w-36 md:w-72 lg:w-80 shrink-0`) with styling indicating an actionable create card (e.g. dashed border, centered plus icon, clear typography, and subtle hover animations).
  23. - **Modal Triggering**: Clicking or pressing Enter/Space on the dummy card must open the `NewAmendmentModal` via `useModal().show()`.
  24. - **Form Submission**:
  25. - The modal must contain inputs for Amendment Name (`name`) and Amendment Description/Content (`content`).
  26. - Submit button must be disabled until required fields are filled.
  27. - On submit, fetch wallet address from `@stellar/freighter-api` and invoke `AmendmentService.addAmendment({ proposalId, creator, name, content })`.
  28. - **Carousel Refresh**: Once submitted successfully, the modal closes and the amendment carousel automatically reloads its list to display the newly proposed amendment.
  29. ### Non-Functional Requirements
  30. - **Consistency**: Visual style must align with the existing Tailwind palette (slate/amber/neutral tones) used in `ProposalDetail.vue` and `ProposalModal.vue`.
  31. - **Accessibility**: Provide proper `role="button"`, `tabindex="0"`, `aria-label`, and keyboard event handlers.
  32. # Technical Design
  33. ### Current Implementation
  34. - `src/components/AmendmentCarousel.vue`: Renders existing amendments using horizontal scroll. Currently ends with a raw placeholder `<article class="...">Add</article>`.
  35. - `src/components/modals/Modal.vue`: Base dialog component with backdrop, keyboard listeners (Esc), headers, and action buttons.
  36. - `src/components/modals/ProposalModal.vue`: Example creation modal utilizing `Modal.vue`, `PostBuilder.vue`, `freighter-api`, and `useModal`.
  37. - `src/composables/useModal.ts`: Controls active modal visibility and dynamic content via `show(component)` and `hide()`.
  38. - `src/generated/typescript/services/AmendmentService.ts`: Provides `addAmendment(requestBody: AddAmendmentRequest)` and `listAmendments(proposalId)`.
  39. ### Key Decisions
  40. 1. **Dedicated `NewAmendmentModal.vue` Component**:
  41. - *Approach*: Create a new modal component specifically for adding amendments rather than overloading the read-only `AmendmentModal.vue`.
  42. - *Rationale*: Keeps concerns separated—`AmendmentModal` focuses on inspecting existing amendments while `NewAmendmentModal` handles form inputs, validation, and wallet signing.
  43. 2. **Context & Refresh Communication**:
  44. - *Approach*: Pass proposal context to the modal and utilize an event emitter or bus notification (`eventBus` or direct callback) upon submission to trigger `getAmendments()` in `AmendmentCarousel.vue`.
  45. - *Rationale*: Avoids full page reload and keeps the carousel responsive.
  46. 3. **Card Presentation**:
  47. - *Approach*: Render the dummy card at the end of the carousel item list with dashed border (`border-2 border-dashed border-slate-300 hover:border-amber-400`), a plus icon from `src/components/icons/Plus.vue`, and descriptive text.
  48. - *Rationale*: Makes it instantly recognizable as an action card while preserving the flow and scroll snapping of the carousel.
  49. ### Proposed Changes
  50. - **`src/components/modals/NewAmendmentModal.vue`** (New File):
  51. - Form layout with `name` input and `PostBuilder` (or markdown content area).
  52. - Validation ensuring `name.trim().length > 0` and content presence.
  53. - Submission handler calling `AmendmentService.addAmendment(...)` with Freighter address.
  54. - Emits `created` event or publishes to `eventBus`.
  55. - **`src/components/AmendmentCarousel.vue`** (Modified):
  56. - Replace raw `Add` article with styled card component.
  57. - Add `openNewAmendmentModal` handler invoking `show(NewAmendmentModal)`.
  58. - Listen for amendment creation events to trigger `getAmendments()`.
  59. ### Architecture Diagram
  60. ```mermaid
  61. graph LR
  62. User[User] -->|Click / Keyboard| DummyCard[Dummy Card in Carousel]
  63. DummyCard -->|useModal.show| NewModal[NewAmendmentModal]
  64. NewModal -->|Sign & Submit| Freighter[Stellar Freighter Wallet]
  65. NewModal -->|addAmendment| Backend[AmendmentService API]
  66. Backend -->|Success| Refresh[Refresh Carousel]
  67. ```
  68. ### File Structure & Changes
  69. - `src/components/modals/NewAmendmentModal.vue`: New creation modal component.
  70. - `src/components/AmendmentCarousel.vue`: Updated dummy card markup, styling, and modal invocation.
  71. - `src/composables/useModal.ts` (if needed): Context helpers for active proposal ID.
  72. # Testing
  73. ### Validation Approach
  74. Verify the feature through interactive testing and automated checks:
  75. - Verify that the dummy card renders correctly within the carousel at different viewport sizes (mobile, tablet, desktop).
  76. - Verify keyboard interactions (Tab navigation, Enter, Space keys) trigger the modal.
  77. - Verify modal form validation (disabling submission on empty fields).
  78. - Verify successful API submission payload structure and carousel refresh.
  79. ### Key Scenarios
  80. 1. **Card Rendering & Styling**:
  81. - Dummy card appears at the end of the amendments carousel.
  82. - Styles match design requirements (dashed border, centered icon, hover transitions).
  83. 2. **Opening the Modal**:
  84. - Clicking the card opens `NewAmendmentModal`.
  85. - Pressing Enter or Space when focused on the card opens `NewAmendmentModal`.
  86. 3. **Submitting New Amendment**:
  87. - Fill in amendment title and body.
  88. - Click "Submit Amendment" -> triggers Freighter authorization and calls `AmendmentService.addAmendment`.
  89. - Modal closes automatically and the new amendment appears in the carousel list.
  90. ### Edge Cases
  91. - **No Wallet Connected / Rejected Signing**: Display appropriate feedback if Freighter rejects connection or signing fails.
  92. - **Empty or Whitespace-only Inputs**: Ensure submit button remains disabled until valid name and content are provided.
  93. - **Carousel Scroll Recalculation**: Ensure `updateEdges()` executes after adding an amendment to update left/right navigation arrows.
  94. # Delivery Steps
  95. ### ✓ Step 1: Create NewAmendmentModal component
  96. A dedicated `NewAmendmentModal.vue` component is created and integrated with the modal system.
  97. - Create `src/components/modals/NewAmendmentModal.vue` utilizing `<Modal>` for the dialog container.
  98. - Implement title input with validation (`name`), content editor (using `PostBuilder` or markdown input), and submit action.
  99. - Integrate with `@stellar/freighter-api` to retrieve the signer address and `AmendmentService.addAmendment` to dispatch the proposal amendment.
  100. - Add error handling, loading state during submission, and automated modal dismissal on success.
  101. ### ✓ Step 2: Implement and style the dummy amendment card in AmendmentCarousel
  102. The carousel placeholder is replaced with a styled, accessible "Add Amendment" dummy card that opens the modal.
  103. - Update the dummy `<article>` in `src/components/AmendmentCarousel.vue` to match carousel card dimensions (`w-36 md:w-72 lg:w-80`) with dashed border and hover effects (`border-2 border-dashed border-slate-300 hover:border-amber-400 bg-slate-50/50 hover:bg-amber-50/60`).
  104. - Embed the `Plus` icon (`src/components/icons/Plus.vue`), title ("Add Amendment"), and descriptive helper text.
  105. - Add keyboard accessibility (`role="button"`, `tabindex="0"`, Enter/Space handlers) and click handler calling `useModal().show(NewAmendmentModal)`.
  106. - Pass current `proposalId` context to the modal so new amendments are attached to the active proposal.
  107. ### ✓ Step 3: Wire submission refresh and carousel reactivity
  108. Amendment creation triggers carousel list reload and seamlessly updates the UI.
  109. - Emit an event or trigger `getAmendments()` in `AmendmentCarousel.vue` upon successful amendment submission.
  110. - Ensure the newly added amendment appears in the carousel without requiring a full page refresh.
  111. - Verify scrolling edge calculations (`updateEdges()`) update after new amendment addition.