From 06f3a4c7c22715213d45d4c470743b2fb17434ea Mon Sep 17 00:00:00 2001 From: Jose Olarte III Date: Sun, 3 Aug 2025 11:49:46 +0800 Subject: [PATCH] Refactor: simplify GiftedDialog with explicit entity type props Replace complex updateEntityTypes() method with explicit giverEntityType and recipientEntityType props. This makes the component more declarative and maintainable by removing hidden logic and making entity type relationships clear at the call site. - Remove updateEntityTypes() method and related watchers - Add explicit giverEntityType and recipientEntityType props with defaults - Update all views to use inline logic for entity type determination - Fix entity type preservation in navigation flows - Enhance query parameter passing for better context preservation - Fix recipient reset issue in ContactGiftingView - Resolve entity type mismatch in HomeView project button flow Files changed: - GiftedDialog.vue: Remove complex logic, add explicit props - EntitySelectionStep.vue: Enhanced query parameter handling - ContactGiftingView.vue: Improved context preservation - HomeView.vue, ProjectViewView.vue, ClaimView.vue, ContactsView.vue: Updated to use explicit entity type props - Add refactoring documentation --- .../GiftedDialog-EntityTypes-Refactoring.md | 207 ++++++++++++++++++ src/components/EntitySelectionStep.vue | 41 ++-- src/components/GiftedDialog.vue | 84 +------ src/views/ClaimView.vue | 3 +- src/views/ContactGiftingView.vue | 42 +++- src/views/ContactsView.vue | 6 +- src/views/HomeView.vue | 6 +- src/views/ProjectViewView.vue | 5 +- 8 files changed, 288 insertions(+), 106 deletions(-) create mode 100644 docs/refactoring/GiftedDialog-EntityTypes-Refactoring.md diff --git a/docs/refactoring/GiftedDialog-EntityTypes-Refactoring.md b/docs/refactoring/GiftedDialog-EntityTypes-Refactoring.md new file mode 100644 index 00000000..78162fd4 --- /dev/null +++ b/docs/refactoring/GiftedDialog-EntityTypes-Refactoring.md @@ -0,0 +1,207 @@ +# GiftedDialog Entity Types Refactoring + +## Overview + +This refactoring simplifies the `GiftedDialog` component by replacing the complex `updateEntityTypes()` method with explicit props for entity types. This makes the component more declarative, reusable, and easier to understand. + +## Problem + +The original `updateEntityTypes()` method used multiple props (`showProjects`, `fromProjectId`, `toProjectId`, `recipientEntityTypeOverride`) to determine entity types through complex conditional logic: + +```typescript +updateEntityTypes() { + // Reset and set entity types based on current context + this.giverEntityType = "person"; + this.recipientEntityType = "person"; + + // If recipient entity type is explicitly overridden, use that + if (this.recipientEntityTypeOverride) { + this.recipientEntityType = this.recipientEntityTypeOverride; + } + + // Determine entity types based on current context + if (this.showProjects) { + // HomeView "Project" button or ProjectViewView "Given by This" + this.giverEntityType = "project"; + // Only override recipient if not already set by recipientEntityTypeOverride + if (!this.recipientEntityTypeOverride) { + this.recipientEntityType = "person"; + } + } else if (this.fromProjectId) { + // ProjectViewView "Given by This" button (project is giver) + this.giverEntityType = "project"; + // Only override recipient if not already set by recipientEntityTypeOverride + if (!this.recipientEntityTypeOverride) { + this.recipientEntityType = "person"; + } + } else if (this.toProjectId) { + // ProjectViewView "Given to This" button (project is recipient) + this.giverEntityType = "person"; + // Only override recipient if not already set by recipientEntityTypeOverride + if (!this.recipientEntityTypeOverride) { + this.recipientEntityType = "project"; + } + } else { + // HomeView "Person" button + this.giverEntityType = "person"; + // Only override recipient if not already set by recipientEntityTypeOverride + if (!this.recipientEntityTypeOverride) { + this.recipientEntityType = "person"; + } + } +} +``` + +### Issues with the Original Approach + +1. **Complex Logic**: Nested conditionals that were hard to follow +2. **Tight Coupling**: Views needed to understand internal logic to set the right props +3. **Inflexible**: Adding new entity type combinations required modifying the method +4. **Unclear Intent**: The relationship between props and entity types was not obvious + +## Solution + +### 1. Explicit Props + +Replace the complex logic with explicit props: + +```typescript +@Prop({ default: "person" }) giverEntityType = "person" as "person" | "project"; +@Prop({ default: "person" }) recipientEntityType = "person" as "person" | "project"; +``` + +### 2. Simple Inline Logic + +Views now use simple inline logic to determine entity types: + +```vue + + + + + + + + +``` + +## Benefits + +### 1. **Declarative** +- Entity types are explicitly declared in the template +- No hidden logic in watchers or complex methods +- Clear intent at the call site + +### 2. **Reusable** +- Views can easily specify any combination of entity types +- No need to understand internal logic +- Simple inline logic is easy to understand + +### 3. **Maintainable** +- Adding new entity type combinations is straightforward +- Logic is visible directly in the template +- No additional files to maintain + +### 4. **Testable** +- Entity type logic is visible and predictable +- No complex state management to test +- Template logic can be easily verified + +### 5. **Type Safe** +- TypeScript ensures correct entity type values +- Compile-time validation of entity type combinations + +## Migration Guide + +### For Views Using GiftedDialog + +Simply update the template to use explicit entity type props: + +```vue + + + + + +``` + +### Common Patterns + +1. **Person-to-Person**: `giver-entity-type="'person'" recipient-entity-type="'person'"` +2. **Project-to-Person**: `giver-entity-type="'project'" recipient-entity-type="'person'"` +3. **Person-to-Project**: `giver-entity-type="'person'" recipient-entity-type="'project'"` +4. **Conditional Project**: `recipient-entity-type="hasProject ? 'project' : 'person'"` + +## Files Changed + +### Core Changes +- `src/components/GiftedDialog.vue` - Removed `updateEntityTypes()` method, added explicit props + +### View Updates +- `src/views/HomeView.vue` - Updated to use inline logic +- `src/views/ProjectViewView.vue` - Updated to use inline logic +- `src/views/ClaimView.vue` - Updated to use inline logic +- `src/views/ContactGiftingView.vue` - Updated to use inline logic +- `src/views/ContactsView.vue` - Updated to use inline logic + +## Backward Compatibility + +The refactoring maintains backward compatibility by: +- Keeping all existing props that are still needed (`fromProjectId`, `toProjectId`, `isFromProjectView`) +- Preserving the same component API for the `open()` method +- Maintaining the same template structure + +## Future Enhancements + +1. **Validation**: Add runtime validation for entity type combinations +2. **Documentation**: Add JSDoc comments to the component props +3. **Testing**: Add unit tests for the component with different entity type combinations + +## Conclusion + +This refactoring transforms `GiftedDialog` from a component with complex internal logic to a declarative, reusable component. The explicit entity type props make the component's behavior clear and predictable, while the simple inline logic keeps the code straightforward and maintainable. + +## Bug Fixes + +### Issue 1: Entity Type Preservation in Navigation + +**Problem**: When navigating from HomeView with `showProjects = true` to ContactGiftingView via "Show All", the entity type information was lost because `showAllQueryParams` returned an empty object for project contexts. + +**Solution**: Modified `EntitySelectionStep.vue` to always pass entity type information in the query parameters, even for project contexts. + +### Issue 2: Recipient Reset in ContactGiftingView + +**Problem**: When selecting a giver in ContactGiftingView, the recipient was always reset to "You" instead of preserving the current recipient. + +**Solution**: Updated ContactGiftingView to preserve the existing recipient from the context when selecting a giver, and enhanced the query parameter passing to include both giver and recipient information for better context preservation. + +### Issue 3: HomeView Project Button Entity Type Mismatch + +**Problem**: When navigating from HomeView Project button → change recipient → Show All → ContactGifting, the giver entity type was incorrectly set to "person" instead of "project". + +**Root Cause**: ContactGiftingView was inferring entity types from `fromProjectId` and `toProjectId` instead of using the explicitly passed `giverEntityType` and `recipientEntityType` from the query parameters. + +**Solution**: Updated ContactGiftingView to use the explicitly passed entity types from query parameters instead of inferring them from project IDs. + +### Files Modified for Bug Fixes + +- `src/components/EntitySelectionStep.vue` - Enhanced query parameter passing +- `src/views/ContactGiftingView.vue` - Improved context preservation logic and entity type handling \ No newline at end of file diff --git a/src/components/EntitySelectionStep.vue b/src/components/EntitySelectionStep.vue index 185fb929..ee144c75 100644 --- a/src/components/EntitySelectionStep.vue +++ b/src/components/EntitySelectionStep.vue @@ -234,11 +234,7 @@ export default class EntitySelectionStep extends Vue { * Query parameters for "Show All" navigation */ get showAllQueryParams(): Record { - if (this.shouldShowProjects) { - return {}; - } - - return { + const baseParams = { stepType: this.stepType, giverEntityType: this.giverEntityType, recipientEntityType: this.recipientEntityType, @@ -247,26 +243,31 @@ export default class EntitySelectionStep extends Vue { amountInput: this.amountInput, unitCode: this.unitCode, offerId: this.offerId, - ...(this.stepType === "giver" - ? { - recipientProjectId: this.toProjectId || "", - recipientProjectName: this.receiver?.name || "", - recipientProjectImage: this.receiver?.image || "", - recipientProjectHandleId: this.receiver?.handleId || "", - recipientDid: this.receiver?.did || "", - } - : { - giverProjectId: this.fromProjectId || "", - giverProjectName: this.giver?.name || "", - giverProjectImage: this.giver?.image || "", - giverProjectHandleId: this.giver?.handleId || "", - giverDid: this.giver?.did || "", - }), fromProjectId: this.fromProjectId, toProjectId: this.toProjectId, showProjects: this.showProjects.toString(), isFromProjectView: this.isFromProjectView.toString(), }; + + if (this.shouldShowProjects) { + // For project contexts, still pass entity type information + return baseParams; + } + + return { + ...baseParams, + // Always pass both giver and recipient info for context preservation + giverProjectId: this.fromProjectId || "", + giverProjectName: this.giver?.name || "", + giverProjectImage: this.giver?.image || "", + giverProjectHandleId: this.giver?.handleId || "", + giverDid: this.giver?.did || "", + recipientProjectId: this.toProjectId || "", + recipientProjectName: this.receiver?.name || "", + recipientProjectImage: this.receiver?.image || "", + recipientProjectHandleId: this.receiver?.handleId || "", + recipientDid: this.receiver?.did || "", + }; } /** diff --git a/src/components/GiftedDialog.vue b/src/components/GiftedDialog.vue index 41166c00..eebce841 100644 --- a/src/components/GiftedDialog.vue +++ b/src/components/GiftedDialog.vue @@ -3,7 +3,7 @@