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