Browse Source
			
			
			
			
				
		- Created complete documentation for GiftedDialog and all 9 child components - Includes architecture diagrams showing component relationships and data flow - Documents props, events, state management, and integration patterns - Covers AmountInput v-model fix and conflict detection logic - Provides usage examples for basic and project context scenarios - Includes testing strategy, performance considerations, and security notes - Features accessibility guidelines and keyboard navigation details - Documents the two-step workflow: entity selection → gift details - Explains the modular architecture with single responsibility components The documentation serves as a complete reference for understanding, maintaining, and extending the GiftedDialog system.matthew-scratch-2025-06-28
				 1 changed files with 224 additions and 0 deletions
			
			
		| @ -0,0 +1,224 @@ | |||
| # GiftedDialog Complete Documentation | |||
| 
 | |||
| ## Overview | |||
| 
 | |||
| The GiftedDialog system is a sophisticated multi-step dialog for recording gifts between people and projects in the TimeSafari application. It consists of a main orchestrating component and 9 specialized child components that handle different aspects of the gift recording workflow. | |||
| 
 | |||
| ## Key Features | |||
| 
 | |||
| - **Two-Step Workflow**: Entity selection → Gift details | |||
| - **Multi-Entity Support**: People, projects, and special entities   | |||
| - **Conflict Detection**: Prevents invalid gift combinations | |||
| - **Responsive Design**: Works across all device sizes | |||
| - **Accessibility**: Full keyboard navigation and screen reader support | |||
| - **Validation**: Comprehensive form validation and error handling | |||
| - **Flexible Integration**: Can be embedded in any view with different contexts | |||
| 
 | |||
| ## Component Architecture | |||
| 
 | |||
| ### Main Component | |||
| - **GiftedDialog.vue** - Main orchestrating component that manages dialog state, step navigation, and API integration | |||
| 
 | |||
| ### Step Components   | |||
| - **EntitySelectionStep.vue** - Step 1 controller with dynamic labeling and context awareness | |||
| - **GiftDetailsStep.vue** - Step 2 controller with form validation and entity summaries | |||
| 
 | |||
| ### Layout Components | |||
| - **EntityGrid.vue** - Unified entity grid layout with responsive design | |||
| - **EntitySummaryButton.vue** - Selected entity display with edit capability | |||
| 
 | |||
| ### Display Components | |||
| - **PersonCard.vue** - Individual person display with avatar and selection states | |||
| - **ProjectCard.vue** - Individual project display with icons and issuer information | |||
| - **SpecialEntityCard.vue** - Special entities (You, Unnamed) with conflict detection | |||
| - **ShowAllCard.vue** - Navigation component with router integration | |||
| 
 | |||
| ### Input Components | |||
| - **AmountInput.vue** - Numeric input with increment/decrement controls and validation | |||
| 
 | |||
| ## Data Flow | |||
| 
 | |||
| ### Step 1: Entity Selection | |||
| 1. User opens dialog → GiftedDialog renders EntitySelectionStep | |||
| 2. EntitySelectionStep renders EntityGrid with entities and configuration | |||
| 3. EntityGrid renders PersonCard/ProjectCard/SpecialEntityCard components | |||
| 4. User clicks entity → Card emits to Grid → Grid emits to Step → Step emits to Dialog | |||
| 5. GiftedDialog updates state and advances to step 2 | |||
| 
 | |||
| ### Step 2: Gift Details   | |||
| 1. GiftedDialog renders GiftDetailsStep with selected entities | |||
| 2. GiftDetailsStep renders EntitySummaryButton and AmountInput components | |||
| 3. User fills form and clicks submit → Step emits to Dialog | |||
| 4. GiftedDialog processes submission via API and handles success/error | |||
| 
 | |||
| ## Key Props and Configuration | |||
| 
 | |||
| ### GiftedDialog Props | |||
| ```typescript | |||
| interface GiftedDialogProps { | |||
|   fromProjectId?: string;      // Project ID when project is giver | |||
|   toProjectId?: string;        // Project ID when project is recipient   | |||
|   showProjects?: boolean;      // Whether to show projects | |||
|   isFromProjectView?: boolean; // Context flag for project views | |||
| } | |||
| ``` | |||
| 
 | |||
| ### Opening the Dialog | |||
| ```typescript | |||
| // Basic usage | |||
| giftedDialog.open(); | |||
| 
 | |||
| // With pre-selected entities and context | |||
| giftedDialog.open( | |||
|   giverEntity,      // Pre-selected giver | |||
|   receiverEntity,   // Pre-selected receiver   | |||
|   offerId,          // Offer context | |||
|   customTitle,      // Custom dialog title | |||
|   prompt,           // Custom input prompt | |||
|   successCallback   // Success handler | |||
| ); | |||
| ``` | |||
| 
 | |||
| ## Integration Patterns | |||
| 
 | |||
| ### Basic Integration | |||
| ```vue | |||
| <template> | |||
|   <div> | |||
|     <button @click="openGiftDialog">Record Gift</button> | |||
|     <GiftedDialog ref="giftedDialog" /> | |||
|   </div> | |||
| </template> | |||
| 
 | |||
| <script lang="ts"> | |||
| export default class Example extends Vue { | |||
|   openGiftDialog() { | |||
|     const dialog = this.$refs.giftedDialog as GiftedDialog; | |||
|     dialog.open(); | |||
|   } | |||
| } | |||
| </script> | |||
| ``` | |||
| 
 | |||
| ### Project Context Integration | |||
| ```typescript | |||
| // Gift from project | |||
| dialog.open( | |||
|   projectEntity,    // Project as giver | |||
|   undefined,        // User selects receiver | |||
|   undefined,        // No offer | |||
|   "Gift from Project", | |||
|   "What did this project provide?" | |||
| ); | |||
| 
 | |||
| // Gift to project   | |||
| dialog.open( | |||
|   undefined,        // User selects giver | |||
|   projectEntity,    // Project as receiver | |||
|   undefined,        // No offer | |||
|   "Gift to Project",  | |||
|   "What was contributed to this project?" | |||
| ); | |||
| ``` | |||
| 
 | |||
| ## State Management | |||
| 
 | |||
| The dialog manages internal state through a reactive system: | |||
| 
 | |||
| - **Step Navigation**: Controls progression from entity selection to gift details | |||
| - **Entity Selection**: Tracks selected giver and receiver entities | |||
| - **Conflict Detection**: Prevents selecting same person for both roles | |||
| - **Form Validation**: Ensures required fields are completed | |||
| - **API Integration**: Handles gift submission and response processing | |||
| 
 | |||
| ## Conflict Detection Logic | |||
| 
 | |||
| ```typescript | |||
| function wouldCreateConflict(selectedDid: string): boolean { | |||
|   // Only applies to person-to-person gifts | |||
|   if (giverEntityType !== "person" || recipientEntityType !== "person") { | |||
|     return false; | |||
|   } | |||
|    | |||
|   // Check if selecting same person for both roles | |||
|   if (stepType === "giver") { | |||
|     return receiver?.did === selectedDid; | |||
|   } else if (stepType === "recipient") { | |||
|     return giver?.did === selectedDid; | |||
|   } | |||
|    | |||
|   return false; | |||
| } | |||
| ``` | |||
| 
 | |||
| ## AmountInput Component Fix | |||
| 
 | |||
| The AmountInput component was recently fixed to resolve an issue where increment/decrement buttons weren't updating the displayed value: | |||
| 
 | |||
| ### Problem | |||
| - Input field used `:value="displayValue"` (one-way binding) | |||
| - Programmatic updates to `displayValue` weren't reflected in DOM | |||
| 
 | |||
| ### Solution   | |||
| - Changed to `v-model="displayValue"` (two-way binding) | |||
| - Now properly synchronizes programmatic and user input changes | |||
| 
 | |||
| ### Usage | |||
| ```vue | |||
| <AmountInput | |||
|   :value="amount" | |||
|   :min="0" | |||
|   :max="1000" | |||
|   :step="1" | |||
|   @update:value="handleAmountChange" | |||
| /> | |||
| ``` | |||
| 
 | |||
| ## Testing Strategy | |||
| 
 | |||
| ### Unit Testing | |||
| - Individual component behavior | |||
| - Props validation | |||
| - Event emission | |||
| - Computed property calculations | |||
| 
 | |||
| ### Integration Testing   | |||
| - Multi-component workflows | |||
| - State management | |||
| - API integration | |||
| - Error handling | |||
| 
 | |||
| ### End-to-End Testing | |||
| - Complete user workflows | |||
| - Cross-browser compatibility | |||
| - Accessibility compliance | |||
| - Performance validation | |||
| 
 | |||
| ## Security Considerations | |||
| 
 | |||
| - **Input Validation**: All user inputs are sanitized and validated | |||
| - **DID Privacy**: User identifiers only shared with authorized contacts   | |||
| - **API Security**: Requests are cryptographically signed | |||
| - **XSS Prevention**: Template sanitization and CSP headers | |||
| 
 | |||
| ## Performance Optimizations | |||
| 
 | |||
| - **Lazy Loading**: Components loaded only when needed | |||
| - **Virtual Scrolling**: For large entity lists | |||
| - **Debounced Input**: Prevents excessive API calls | |||
| - **Computed Properties**: Efficient reactive calculations | |||
| - **Memory Management**: Proper cleanup on component destruction | |||
| 
 | |||
| ## Accessibility Features | |||
| 
 | |||
| - **Keyboard Navigation**: Full tab order and keyboard shortcuts | |||
| - **Screen Reader Support**: ARIA labels and semantic HTML | |||
| - **Focus Management**: Proper focus handling on open/close | |||
| - **High Contrast**: Supports high contrast themes | |||
| - **Responsive Design**: Works on all screen sizes | |||
| 
 | |||
| --- | |||
| 
 | |||
| **Author**: Matthew Raymer   | |||
| **Last Updated**: 2025-06-30   | |||
| **Version**: 1.0.0 | |||
					Loading…
					
					
				
		Reference in new issue