@ -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
@ -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
@ -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
@ -1015,9 +1258,13 @@ test('Gift recording workflow', async ({ page }) => {
### Optimization Strategies
1. **Lazy Loading** : Components are loaded only when needed
2. **Virtual Scrolling** : For large entity lists
3. **Debounced Input** : Amount input changes are debounced
4. **Computed Properties** : Efficient reactive calculations
5. **Event Delegation** : Minimal event listeners
### Memory Management
@ -1040,8 +1287,11 @@ export default class GiftedDialog extends Vue {
### Bundle Size Optimization
- Tree-shaking for unused FontAwesome icons
- Dynamic imports for heavy components
- Shared dependencies between components
- Minimal external dependencies
## Accessibility Features
@ -1049,8 +1299,11 @@ export default class GiftedDialog extends Vue {
### Keyboard Navigation
- Tab order follows visual flow
- Enter/Space for button activation
- Escape to close dialog
- Arrow keys for amount input
### Screen Reader Support