Browse Source

fix(home): resolve nearby filter not refreshing feed view

- Fix FeedFilters component missing activeDid context for settings updates
- Update reloadFeedOnChange to retrieve actual settings without defaults
- Add comprehensive logging throughout feed refresh process for debugging
- Ensure filter state changes immediately trigger feed refresh without page reload

The issue was caused by FeedFilters component calling $updateSettings() without
the activeDid parameter, causing settings to be saved to wrong location. Now
properly passes activeDid from HomeView and uses $accountSettings() for
accurate user-specific settings retrieval.

Closes filter refresh issue where turning ON nearby filter required page reload
pull/162/head
Matthew Raymer 5 days ago
parent
commit
9196081f34
  1. 5
      src/components/DataExportSection.vue
  2. 61
      src/components/FeedFilters.vue
  3. 6
      src/components/OfferDialog.vue
  4. 108
      src/views/HomeView.vue

5
src/components/DataExportSection.vue

@ -187,9 +187,10 @@ export default class DataExportSection extends Vue {
const exContact: Contact = R.omit(["contactMethods"], contact); const exContact: Contact = R.omit(["contactMethods"], contact);
// now add contactMethods as a true array of ContactMethod objects // now add contactMethods as a true array of ContactMethod objects
exContact.contactMethods = contact.contactMethods exContact.contactMethods = contact.contactMethods
? (typeof contact.contactMethods === 'string' && contact.contactMethods.trim() !== '' ? typeof contact.contactMethods === "string" &&
contact.contactMethods.trim() !== ""
? JSON.parse(contact.contactMethods) ? JSON.parse(contact.contactMethods)
: []) : []
: []; : [];
return exContact; return exContact;
}); });

61
src/components/FeedFilters.vue

@ -119,11 +119,13 @@ export default class FeedFilters extends Vue {
isNearby = false; isNearby = false;
settingChanged = false; settingChanged = false;
visible = false; visible = false;
activeDid = "";
async open(onCloseIfChanged: () => void) { async open(onCloseIfChanged: () => void, activeDid: string) {
this.onCloseIfChanged = onCloseIfChanged; this.onCloseIfChanged = onCloseIfChanged;
this.activeDid = activeDid;
const settings = await this.$settings(); const settings = await this.$accountSettings(activeDid);
this.hasVisibleDid = !!settings.filterFeedByVisible; this.hasVisibleDid = !!settings.filterFeedByVisible;
this.isNearby = !!settings.filterFeedByNearby; this.isNearby = !!settings.filterFeedByNearby;
if (settings.searchBoxes && settings.searchBoxes.length > 0) { if (settings.searchBoxes && settings.searchBoxes.length > 0) {
@ -137,28 +139,66 @@ export default class FeedFilters extends Vue {
async toggleHasVisibleDid() { async toggleHasVisibleDid() {
this.settingChanged = true; this.settingChanged = true;
this.hasVisibleDid = !this.hasVisibleDid; this.hasVisibleDid = !this.hasVisibleDid;
if (this.activeDid) {
await this.$updateSettings(
{
filterFeedByVisible: this.hasVisibleDid,
},
this.activeDid,
);
} else {
await this.$updateSettings({ await this.$updateSettings({
filterFeedByVisible: this.hasVisibleDid, filterFeedByVisible: this.hasVisibleDid,
}); });
} }
}
async toggleNearby() { async toggleNearby() {
this.settingChanged = true; this.settingChanged = true;
this.isNearby = !this.isNearby; this.isNearby = !this.isNearby;
console.log("[FeedFilters] 🔄 Toggling nearby filter:", {
newValue: this.isNearby,
settingChanged: this.settingChanged,
activeDid: this.activeDid,
});
if (this.activeDid) {
await this.$updateSettings(
{
filterFeedByNearby: this.isNearby,
},
this.activeDid,
);
} else {
await this.$updateSettings({ await this.$updateSettings({
filterFeedByNearby: this.isNearby, filterFeedByNearby: this.isNearby,
}); });
} }
console.log("[FeedFilters] ✅ Nearby filter updated in settings");
}
async clearAll() { async clearAll() {
if (this.hasVisibleDid || this.isNearby) { if (this.hasVisibleDid || this.isNearby) {
this.settingChanged = true; this.settingChanged = true;
} }
if (this.activeDid) {
await this.$updateSettings(
{
filterFeedByNearby: false,
filterFeedByVisible: false,
},
this.activeDid,
);
} else {
await this.$updateSettings({ await this.$updateSettings({
filterFeedByNearby: false, filterFeedByNearby: false,
filterFeedByVisible: false, filterFeedByVisible: false,
}); });
}
this.hasVisibleDid = false; this.hasVisibleDid = false;
this.isNearby = false; this.isNearby = false;
@ -169,23 +209,40 @@ export default class FeedFilters extends Vue {
this.settingChanged = true; this.settingChanged = true;
} }
if (this.activeDid) {
await this.$updateSettings(
{
filterFeedByNearby: true,
filterFeedByVisible: true,
},
this.activeDid,
);
} else {
await this.$updateSettings({ await this.$updateSettings({
filterFeedByNearby: true, filterFeedByNearby: true,
filterFeedByVisible: true, filterFeedByVisible: true,
}); });
}
this.hasVisibleDid = true; this.hasVisibleDid = true;
this.isNearby = true; this.isNearby = true;
} }
close() { close() {
console.log("[FeedFilters] 🚪 Closing dialog:", {
settingChanged: this.settingChanged,
hasCallback: !!this.onCloseIfChanged,
});
if (this.settingChanged) { if (this.settingChanged) {
console.log("[FeedFilters] 🔄 Settings changed, calling callback");
this.onCloseIfChanged(); this.onCloseIfChanged();
} }
this.visible = false; this.visible = false;
} }
done() { done() {
console.log("[FeedFilters] ✅ Done button clicked");
this.close(); this.close();
} }
} }

6
src/components/OfferDialog.vue

@ -18,7 +18,7 @@ Raymer */
<div class="flex mb-4"> <div class="flex mb-4">
<AmountInput <AmountInput
:value="parseFloat(amountInput) || 0" :value="parseFloat(amountInput) || 0"
:onUpdateValue="handleAmountUpdate" :on-update-value="handleAmountUpdate"
data-testId="inputOfferAmount" data-testId="inputOfferAmount"
/> />
@ -152,8 +152,6 @@ export default class OfferDialog extends Vue {
}; };
} }
// ================================================= // =================================================
// COMPONENT METHODS // COMPONENT METHODS
// ================================================= // =================================================
@ -199,8 +197,6 @@ export default class OfferDialog extends Vue {
this.visible = false; this.visible = false;
} }
/** /**
* Handle amount updates from AmountInput component * Handle amount updates from AmountInput component
* @param value - New amount value * @param value - New amount value

108
src/views/HomeView.vue

@ -763,17 +763,34 @@ export default class HomeView extends Vue {
* Called by FeedFilters component when filters change * Called by FeedFilters component when filters change
*/ */
async reloadFeedOnChange() { async reloadFeedOnChange() {
const settings = await this.$accountSettings(this.activeDid, { logger.info("[HomeView] 🔄 reloadFeedOnChange() called - refreshing feed");
filterFeedByVisible: false,
filterFeedByNearby: false, // Get current settings without overriding with defaults
const settings = await this.$accountSettings(this.activeDid);
logger.info("[HomeView] 📊 Current filter settings:", {
filterFeedByVisible: settings.filterFeedByVisible,
filterFeedByNearby: settings.filterFeedByNearby,
searchBoxes: settings.searchBoxes?.length || 0,
}); });
this.isFeedFilteredByVisible = !!settings.filterFeedByVisible; this.isFeedFilteredByVisible = !!settings.filterFeedByVisible;
this.isFeedFilteredByNearby = !!settings.filterFeedByNearby; this.isFeedFilteredByNearby = !!settings.filterFeedByNearby;
this.isAnyFeedFilterOn = checkIsAnyFeedFilterOn(settings); this.isAnyFeedFilterOn = checkIsAnyFeedFilterOn(settings);
logger.info("[HomeView] 🎯 Updated filter states:", {
isFeedFilteredByVisible: this.isFeedFilteredByVisible,
isFeedFilteredByNearby: this.isFeedFilteredByNearby,
isAnyFeedFilterOn: this.isAnyFeedFilterOn,
});
this.feedData = []; this.feedData = [];
this.feedPreviousOldestId = undefined; this.feedPreviousOldestId = undefined;
logger.info("[HomeView] 🧹 Cleared feed data, calling updateAllFeed()");
await this.updateAllFeed(); await this.updateAllFeed();
logger.info("[HomeView] ✅ Feed refresh completed");
} }
/** /**
@ -852,6 +869,14 @@ export default class HomeView extends Vue {
* - this.feedLastViewedClaimId (via updateFeedLastViewedId) * - this.feedLastViewedClaimId (via updateFeedLastViewedId)
*/ */
async updateAllFeed() { async updateAllFeed() {
logger.info("[HomeView] 🚀 updateAllFeed() called", {
isFeedLoading: this.isFeedLoading,
currentFeedDataLength: this.feedData.length,
isAnyFeedFilterOn: this.isAnyFeedFilterOn,
isFeedFilteredByVisible: this.isFeedFilteredByVisible,
isFeedFilteredByNearby: this.isFeedFilteredByNearby,
});
this.isFeedLoading = true; this.isFeedLoading = true;
let endOfResults = true; let endOfResults = true;
@ -860,21 +885,37 @@ export default class HomeView extends Vue {
this.apiServer, this.apiServer,
this.feedPreviousOldestId, this.feedPreviousOldestId,
); );
logger.info("[HomeView] 📡 Retrieved gives from API", {
resultsCount: results.data.length,
endOfResults,
});
if (results.data.length > 0) { if (results.data.length > 0) {
endOfResults = false; endOfResults = false;
// gather any contacts that user has blocked from view // gather any contacts that user has blocked from view
await this.processFeedResults(results.data); await this.processFeedResults(results.data);
await this.updateFeedLastViewedId(results.data); await this.updateFeedLastViewedId(results.data);
logger.info("[HomeView] 📝 Processed feed results", {
processedCount: this.feedData.length,
});
} }
} catch (e) { } catch (e) {
logger.error("[HomeView] ❌ Error in updateAllFeed:", e);
this.handleFeedError(e); this.handleFeedError(e);
} }
if (this.feedData.length === 0 && !endOfResults) { if (this.feedData.length === 0 && !endOfResults) {
logger.info("[HomeView] 🔄 No results after filtering, retrying...");
await this.updateAllFeed(); await this.updateAllFeed();
} }
this.isFeedLoading = false; this.isFeedLoading = false;
logger.info("[HomeView] ✅ updateAllFeed() completed", {
finalFeedDataLength: this.feedData.length,
isFeedLoading: this.isFeedLoading,
});
} }
/** /**
@ -899,12 +940,35 @@ export default class HomeView extends Vue {
* @param records Array of feed records to process * @param records Array of feed records to process
*/ */
private async processFeedResults(records: GiveSummaryRecord[]) { private async processFeedResults(records: GiveSummaryRecord[]) {
logger.info("[HomeView] 📝 Processing feed results:", {
inputRecords: records.length,
currentFilters: {
isAnyFeedFilterOn: this.isAnyFeedFilterOn,
isFeedFilteredByVisible: this.isFeedFilteredByVisible,
isFeedFilteredByNearby: this.isFeedFilteredByNearby,
},
});
let processedCount = 0;
let filteredCount = 0;
for (const record of records) { for (const record of records) {
const processedRecord = await this.processRecord(record); const processedRecord = await this.processRecord(record);
if (processedRecord) { if (processedRecord) {
this.feedData.push(processedRecord); this.feedData.push(processedRecord);
processedCount++;
} else {
filteredCount++;
} }
} }
logger.info("[HomeView] 📊 Feed processing results:", {
processed: processedCount,
filtered: filteredCount,
total: records.length,
finalFeedLength: this.feedData.length,
});
this.feedPreviousOldestId = records[records.length - 1].jwtId; this.feedPreviousOldestId = records[records.length - 1].jwtId;
} }
@ -938,7 +1002,7 @@ export default class HomeView extends Vue {
* - this.feedData (via createFeedRecord) * - this.feedData (via createFeedRecord)
* *
* @param record The record to process * @param record The record to process
* @returns Processed record with contact info if it passes filters, null otherwise * @returns Processed record if it passes filters, null otherwise
*/ */
private async processRecord( private async processRecord(
record: GiveSummaryRecord, record: GiveSummaryRecord,
@ -948,13 +1012,28 @@ export default class HomeView extends Vue {
const recipientDid = this.extractRecipientDid(claim); const recipientDid = this.extractRecipientDid(claim);
const fulfillsPlan = await this.getFulfillsPlan(record); const fulfillsPlan = await this.getFulfillsPlan(record);
// Log record details for debugging
logger.debug("[HomeView] 🔍 Processing record:", {
recordId: record.jwtId,
hasFulfillsPlan: !!fulfillsPlan,
fulfillsPlanHandleId: record.fulfillsPlanHandleId,
filters: {
isAnyFeedFilterOn: this.isAnyFeedFilterOn,
isFeedFilteredByVisible: this.isFeedFilteredByNearby,
isFeedFilteredByNearby: this.isFeedFilteredByNearby,
},
});
if (!this.shouldIncludeRecord(record, fulfillsPlan)) { if (!this.shouldIncludeRecord(record, fulfillsPlan)) {
logger.debug("[HomeView] ❌ Record filtered out:", record.jwtId);
return null; return null;
} }
const provider = this.extractProvider(claim); const provider = this.extractProvider(claim);
const providedByPlan = await this.getProvidedByPlan(provider); const providedByPlan = await this.getProvidedByPlan(provider);
logger.debug("[HomeView] ✅ Record included:", record.jwtId);
return this.createFeedRecord( return this.createFeedRecord(
record, record,
claim, claim,
@ -1103,6 +1182,22 @@ export default class HomeView extends Vue {
} }
} }
// Add debug logging for nearby filter
if (this.isFeedFilteredByNearby && record.fulfillsPlanHandleId) {
logger.debug("[HomeView] 🔍 Nearby filter check:", {
recordId: record.jwtId,
hasFulfillsPlan: !!fulfillsPlan,
hasLocation: !!(fulfillsPlan?.locLat && fulfillsPlan?.locLon),
location: fulfillsPlan
? { lat: fulfillsPlan.locLat, lon: fulfillsPlan.locLon }
: null,
inSearchBox: fulfillsPlan
? this.latLongInAnySearchBox(fulfillsPlan.locLat, fulfillsPlan.locLon)
: null,
finalResult: anyMatch,
});
}
return anyMatch; return anyMatch;
} }
@ -1538,7 +1633,10 @@ export default class HomeView extends Vue {
* Called by template click handler * Called by template click handler
*/ */
openFeedFilters() { openFeedFilters() {
(this.$refs.feedFilters as FeedFilters).open(this.reloadFeedOnChange); (this.$refs.feedFilters as FeedFilters).open(
this.reloadFeedOnChange,
this.activeDid,
);
} }
/** /**

Loading…
Cancel
Save