diff --git a/GiftedDialog-Complete-Documentation.md b/GiftedDialog-Complete-Documentation.md index e8e5ed0b..e2573c9d 100644 --- a/GiftedDialog-Complete-Documentation.md +++ b/GiftedDialog-Complete-Documentation.md @@ -20,19 +20,29 @@ The GiftedDialog system is a sophisticated multi-step dialog for recording gifts ### 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 ### Design Principles - **Single Responsibility**: Each component has one clear purpose + - **Composition over Inheritance**: Built through component composition + - **Reactive Data Flow**: Vue's reactivity system for state management + - **Progressive Enhancement**: Core functionality works without JavaScript + - **Privacy by Design**: Respects user privacy and data sovereignty ## Architecture Diagram @@ -41,7 +51,7 @@ The GiftedDialog system is a sophisticated multi-step dialog for recording gifts graph TB subgraph "GiftedDialog System" GD[GiftedDialog.vue
Main Orchestrator] - + subgraph "Step 1: Entity Selection" ESS[EntitySelectionStep.vue
Step Controller] EG[EntityGrid.vue
Layout Manager] @@ -50,13 +60,13 @@ graph TB SEC[SpecialEntityCard.vue
Special Entities] SAC[ShowAllCard.vue
Navigation] end - + subgraph "Step 2: Gift Details" GDS[GiftDetailsStep.vue
Form Controller] ESB[EntitySummaryButton.vue
Entity Summary] AI[AmountInput.vue
Amount Control] end - + subgraph "External Dependencies" EI[EntityIcon.vue
Icon Renderer] PI[ProjectIcon.vue
Project Icons] @@ -65,7 +75,7 @@ graph TB ROUTER[Vue Router] end end - + GD --> ESS GD --> GDS ESS --> EG @@ -84,26 +94,162 @@ graph TB SAC --> ROUTER ``` +### ASCII Art Architecture Diagram + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ GiftedDialog System │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ GiftedDialog.vue │ │ +│ │ Main Orchestrator │ │ +│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ +│ │ │ Dialog State │ │ Step Control │ │ API Integration│ │ │ +│ │ │ Management │ │ (1 ↔ 2) │ │ & Validation │ │ │ +│ │ │ │ │ │ │ │ └─────────────────┘ └─────────────────┘ │ │ +│ │ └──────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ Step 1: Entity Selection │ │ +│ │ │ │ +│ │ ┌─────────────────────────────────────────────────────────────┐ │ │ +│ │ │ EntitySelectionStep.vue │ │ │ +│ │ │ Step Controller │ │ │ +│ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ +│ │ │ │ Context │ │ Conflict │ │ Dynamic │ │ │ │ +│ │ │ │ Awareness │ │ Detection │ │ Labeling │ │ │ │ +│ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ +│ │ └─────────────────────────────────────────────────────────────┘ │ │ +│ │ │ │ │ +│ │ ▼ │ │ +│ │ ┌─────────────────────────────────────────────────────────────┐ │ │ +│ │ │ EntityGrid.vue │ │ │ +│ │ │ Layout Manager │ │ │ +│ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ +│ │ │ │ Responsive │ │ Event │ │ Empty State │ │ │ │ +│ │ │ │ Grid Layout │ │ Delegation │ │ Handling │ │ │ │ +│ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ +│ │ └─────────────────────────────────────────────────────────────┘ │ │ +│ │ │ │ │ +│ │ ▼ │ │ +│ │ ┌─────────────────────────────────────────────────────────────┐ │ │ +│ │ │ Entity Display Components │ │ │ +│ │ │ ┌─────────── ──┐ ┌─────────────┐ ┌─────────────┐ │ │ │ +│ │ │ │ PersonCard │ │ProjectCard │ │SpecialEntity│ │ │ │ +│ │ │ │ Avatar, Name │ │Icon, Name │ │Card (You, │ │ │ │ +│ │ │ │ Selection │ │Issuer Info │ │Unnamed) │ │ │ │ +│ │ │ └──────────── ─┘ └─────────────┘ └─────────────┘ │ │ │ +│ │ └─────────────────────────────────────────────────────────────┘ │ │ +│ │ │ │ │ +│ │ ▼ │ │ +│ │ ┌─────────────────────────────────────────────────────────────┐ │ │ +│ │ │ ShowAllCard.vue │ │ │ +│ │ │ Navigation Component │ │ │ +│ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ +│ │ │ │ Router │ │ Query │ │ Context │ │ │ │ +│ │ │ │ Integration │ │ Parameters │ │ Preservation│ │ │ │ +│ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ +│ │ └─────────────────────────────────────────────────────────────┘ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ Step 2: Gift Details │ │ +│ │ │ │ +│ │ ┌─────────────────────────────────────────────────────────────┐ │ │ +│ │ │ GiftDetailsStep.vue │ │ │ +│ │ │ Form Controller │ │ │ +│ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ +│ │ │ │ Form │ │ Validation │ │ Conflict │ │ │ │ +│ │ │ │ Management │ │ & Error │ │ Warning │ │ │ │ +│ │ │ │ │ │ Handling │ │ Display │ │ │ │ +│ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ +│ │ └─────────────────────────────────────────────────────────────┘ │ │ +│ │ │ │ │ +│ │ ▼ │ │ +│ │ ┌─────────────────────────────────────────────────────────────┐ │ │ +│ │ │ Form Input Components │ │ │ +│ │ │ ┌──────────── ─┐ ┌─────────────┐ ┌─────────────┐ │ │ │ +│ │ │ │EntitySummary │ │AmountInput │ │Description │ │ │ │ +│ │ │ │Button │ │Increment/ │ │Input │ │ │ │ +│ │ │ │Edit Capability│ │Decrement │ │Placeholder │ │ │ │ +│ │ │ └─────────── ──┘ └─────────────┘ └─────────────┘ │ │ │ +│ │ └─────────────────────────────────────────────────────────────┘ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ External Dependencies │ │ +│ │ │ │ +│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ +│ │ │ EntityIcon │ │ProjectIcon │ │ Database │ │ Endorser │ │ │ +│ │ │ Avatar │ │ Project │ │ Layer │ │ API │ │ │ +│ │ │ Renderer │ │ Images │ │ SQLite │ │ Claims │ │ │ +│ │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │ +│ │ │ │ +│ │ ┌─────────────────────────────────────────────────────────────┐ │ │ +│ │ │ Vue Router │ │ │ +│ │ │ Navigation & Deep Linking │ │ │ +│ │ └─────────────────────────────────────────────────────────────┘ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ + +Data Flow: +┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ +│ User │──▶│ GiftedDialog│──▶│ Step 1 │──▶│ Entity │ +│ Interaction │ │ Main │ │ Selection │ │ Selection │ +└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ + │ │ │ + ▼ ▼ ▼ +┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ +│ Success/ │◀──│ API │◀──│ Step 2 │◀──│ Form │ +│ Error │ │ Integration │ │ Details │ │ Submission │ +│ Handling │ │ │ │ │ │ │ +└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ + +Component Communication: +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Event Flow: entity-selected → update:amount → submit → gift-recorded │ +│ │ +│ State Flow: Dialog State → Step State → Form State → API State │ +│ │ +│ Data Flow: Props Down → Events Up → Callbacks → Parent Notification │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + ## Component Hierarchy ### Main Component + - **GiftedDialog.vue** - Main orchestrating component ### Step Components + - **EntitySelectionStep.vue** - Step 1 controller + - **GiftDetailsStep.vue** - Step 2 controller ### Layout Components + - **EntityGrid.vue** - Unified entity grid layout + - **EntitySummaryButton.vue** - Selected entity display ### Display Components + - **PersonCard.vue** - Individual person display + - **ProjectCard.vue** - Individual project display + - **SpecialEntityCard.vue** - Special entities (You, Unnamed) + - **ShowAllCard.vue** - Navigation component ### Input Components + - **AmountInput.vue** - Numeric input with controls ## Data Flow Diagrams @@ -118,13 +264,13 @@ sequenceDiagram participant EntityGrid participant PersonCard participant SpecialEntityCard - + User->>GiftedDialog: Open dialog GiftedDialog->>EntitySelectionStep: Render step 1 EntitySelectionStep->>EntityGrid: Pass entities & config EntityGrid->>PersonCard: Render people EntityGrid->>SpecialEntityCard: Render special entities - + User->>PersonCard: Click person PersonCard->>EntityGrid: emit person-selected EntityGrid->>EntitySelectionStep: emit entity-selected @@ -141,16 +287,16 @@ sequenceDiagram participant GiftDetailsStep participant EntitySummaryButton participant AmountInput - + GiftedDialog->>GiftDetailsStep: Render step 2 GiftDetailsStep->>EntitySummaryButton: Display selected entities GiftDetailsStep->>AmountInput: Render amount input - + User->>AmountInput: Click increment AmountInput->>GiftDetailsStep: emit update:value GiftDetailsStep->>GiftedDialog: emit update:amount GiftedDialog->>GiftedDialog: Update amount state - + User->>GiftDetailsStep: Click submit GiftDetailsStep->>GiftedDialog: emit submit GiftedDialog->>GiftedDialog: Process & submit gift @@ -178,14 +324,21 @@ flowchart TD **Purpose**: Main orchestrating component that manages the overall dialog state and workflow. **Key Responsibilities**: + - Dialog visibility and lifecycle management + - Step navigation (1 → 2) + - Entity conflict detection + - API integration for gift submission + - Success/error handling + - Child component coordination **Props**: + ```typescript interface GiftedDialogProps { fromProjectId?: string; // Project ID when project is giver @@ -196,13 +349,19 @@ interface GiftedDialogProps { ``` **Key Methods**: + - `open()` - Initialize and show dialog + - `cancel()` - Close dialog and reset state + - `confirm()` - Submit gift and handle response + - `handleEntitySelected()` - Process entity selection from step 1 + - `handleSubmit()` - Process form submission from step 2 **State Management**: + ```typescript interface GiftedDialogState { visible: boolean; @@ -221,13 +380,19 @@ interface GiftedDialogState { **Purpose**: Complete step 1 interface for entity selection with dynamic labeling and context awareness. **Key Features**: + - Dynamic step labeling based on context + - EntityGrid integration for unified display + - Conflict detection and prevention + - Special entity handling + - Context preservation for navigation **Props**: + ```typescript interface EntitySelectionStepProps { stepType: 'giver' | 'recipient'; @@ -248,11 +413,17 @@ interface EntitySelectionStepProps { ``` **Computed Properties**: + - `stepLabel` - Dynamic label based on context + - `shouldShowProjects` - Whether to show projects vs people + - `shouldShowYouEntity` - Whether to show "You" option + - `youSelectable` - Whether "You" can be selected + - `showAllRoute` - Navigation route for "Show All" + - `showAllQueryParams` - Query parameters for navigation ### 3. GiftDetailsStep.vue @@ -260,14 +431,21 @@ interface EntitySelectionStepProps { **Purpose**: Complete step 2 interface for gift details with form validation and entity summaries. **Key Features**: + - Entity summary display with edit capability + - Gift description input with placeholder support + - Amount input with increment/decrement controls + - Unit code selection (HUR, USD, BTC, etc.) + - Conflict detection and warning display + - Form validation and submission **Props**: + ```typescript interface GiftDetailsStepProps { giver: EntityData | null; @@ -287,6 +465,7 @@ interface GiftDetailsStepProps { ``` **Local State**: + ```typescript interface GiftDetailsLocalState { localDescription: string; @@ -300,14 +479,21 @@ interface GiftDetailsLocalState { **Purpose**: Unified grid layout for displaying people, projects, and special entities with responsive design. **Key Features**: + - Responsive grid layout (3-6 columns based on entity type) + - Special entity integration (You, Unnamed) + - Conflict detection integration + - Empty state messaging + - Show All navigation + - Event delegation for entity selection **Props**: + ```typescript interface EntityGridProps { entityType: 'people' | 'projects'; @@ -325,6 +511,7 @@ interface EntityGridProps { ``` **Grid Layout**: + - **People**: 4-6 columns (responsive) - **Projects**: 3-4 columns (responsive) - **Special entities**: Always shown for people grids @@ -335,13 +522,19 @@ interface EntityGridProps { **Purpose**: Individual person display with avatar, name, and selection states. **Key Features**: + - EntityIcon integration for avatar display + - Conflict state visualization + - Time icon display for activity context + - Hover and selection states + - Accessibility support **Props**: + ```typescript interface PersonCardProps { person: Contact; @@ -351,9 +544,13 @@ interface PersonCardProps { ``` **Visual States**: + - **Normal**: Default appearance + - **Conflicted**: Red border, disabled state + - **Hovered**: Elevated appearance + - **Selected**: Highlighted border ### 6. ProjectCard.vue @@ -361,10 +558,15 @@ interface PersonCardProps { **Purpose**: Individual project display with project icon, name, and issuer information. **Key Features**: + - ProjectIcon integration for project images + - Issuer information display + - Project name with ellipsis overflow + - Selection state management + - Accessibility support **Props**: @@ -378,9 +580,13 @@ interface ProjectCardProps { ``` **Display Elements**: + - Project icon/image + - Project name (truncated) + - Issuer information + - Selection indicator ### 7. SpecialEntityCard.vue @@ -388,10 +594,15 @@ interface ProjectCardProps { **Purpose**: Special entity display for "You" and "Unnamed" with conflict detection. **Key Features**: + - FontAwesome icon integration + - Conflict state handling + - Conditional selectability + - Consistent styling with other cards + - Accessibility support **Props**: @@ -407,7 +618,9 @@ interface SpecialEntityCardProps { ``` **Entity Types**: + - **You**: Represents the current user + - **Unnamed**: Represents anonymous giver ### 8. ShowAllCard.vue @@ -415,10 +628,15 @@ interface SpecialEntityCardProps { **Purpose**: Navigation component for "Show All" functionality with router integration. **Key Features**: + - Vue Router integration + - Query parameter passing + - Context preservation + - Consistent styling + - Icon-based navigation **Props**: @@ -431,8 +649,11 @@ interface ShowAllCardProps { ``` **Navigation Logic**: + - People → ContactGiftingView with context + - Projects → DiscoverView + - Query parameters preserve dialog state ### 9. EntitySummaryButton.vue @@ -440,10 +661,15 @@ interface ShowAllCardProps { **Purpose**: Selected entity display with edit capability for step 2. **Key Features**: + - EntityIcon/ProjectIcon integration + - Edit button functionality + - Entity type detection + - Consistent styling + - Accessibility support **Props**: @@ -457,9 +683,13 @@ interface EntitySummaryButtonProps { ``` **Display Elements**: + - Entity icon/avatar + - Entity name + - Edit button (when editable) + - Type-specific styling ### 10. AmountInput.vue @@ -467,10 +697,15 @@ interface EntitySummaryButtonProps { **Purpose**: Specialized numeric input with increment/decrement controls and validation. **Key Features**: + - Increment/decrement buttons + - Configurable min/max values and step size + - Input validation and formatting + - Disabled state handling for boundary values + - v-model compatibility **Props**: @@ -485,15 +720,23 @@ interface AmountInputProps { ``` **Key Methods**: + - `increment()` - Increase value by step + - `decrement()` - Decrease value by step + - `handleInput()` - Process direct input + - `handleBlur()` - Validate on blur **Validation Logic**: + - Minimum/maximum bounds checking + - Step size validation + - Numeric input sanitization + - Real-time feedback ## Integration Patterns @@ -552,11 +795,11 @@ export default class ParentComponent extends Vue { text: `Successfully recorded gift of ${amount} hours`, type: "success" }); - + // Refresh data if needed this.loadActivities(); } - + openGiftDialog() { const dialog = this.$refs.giftedDialog as GiftedDialog; dialog.open( @@ -616,14 +859,14 @@ function wouldCreateConflict(selectedDid: string): boolean { 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; } ``` @@ -638,7 +881,7 @@ sequenceDiagram participant Grid as EntityGrid participant Step as EntitySelectionStep participant Dialog as GiftedDialog - + Card->>Grid: emit entity-selected Grid->>Step: emit entity-selected Step->>Dialog: emit entity-selected @@ -655,7 +898,7 @@ sequenceDiagram participant Dialog as GiftedDialog participant API as Endorser API participant Parent as Parent Component - + Form->>Dialog: emit submit Dialog->>Dialog: handleSubmit() Dialog->>API: createAndSubmitGive() @@ -672,7 +915,7 @@ sequenceDiagram participant Input as AmountInput participant Step as GiftDetailsStep participant Dialog as GiftedDialog - + Input->>Step: emit update:value Step->>Dialog: emit update:amount Dialog->>Dialog: handleAmountUpdate() @@ -687,7 +930,7 @@ sequenceDiagram