Skip to content

did some code refactoring for inconsitent data handling#103

Merged
Embers2512 merged 3 commits intoSofteng310:mainfrom
ntur101:refactoring/inconsitent-data-handling
Oct 19, 2025
Merged

did some code refactoring for inconsitent data handling#103
Embers2512 merged 3 commits intoSofteng310:mainfrom
ntur101:refactoring/inconsitent-data-handling

Conversation

@ntur101
Copy link
Copy Markdown
Collaborator

@ntur101 ntur101 commented Oct 19, 2025

📌 Description

What does this PR do?
Centralizes all Firestore data transformation and timestamp normalization logic into a single services/firestoreNormalizer.js file to eliminate duplication and inconsistencies across the app.

Why is it needed?
Previously, multiple components handled Firestore data differently, causing inconsistent formats, repeated code, and harder maintenance. This refactor standardizes and simplifies data handling.

🔗 Related Issue(s)

Closes #102

✅ Changes

[x] Refactor

🧪 How to Test

Run existing unit and integration tests — all should pass.

Verify data displays correctly in Feed, Messages, and Profile pages.

Check that timestamps and field names (e.g., imageURL, date) appear consistent across all views.

Copilot AI review requested due to automatic review settings October 19, 2025 21:37
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Centralizes Firestore data normalization into a single service and updates consumers to use it for consistent timestamp and field handling across the app.

  • Introduces services/firestoreNormalizer.js with normalization utilities and unit tests.
  • Refactors Messages and Profile pages, and the UI utils wrapper, to consume the new normalizers.
  • Standardizes timestamps to ISO strings and unifies field name variations (e.g., imageURL/imageUrl).

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
frontend/src/services/firestoreNormalizer.js New normalization utilities for items, users, messages, conversations, and announcements, plus helpers.
frontend/src/services/firestoreNormalizer.test.js Unit tests covering timestamp handling and object normalizers.
frontend/src/pages/Messages.js Refactors fetching, sorting, and rendering to use normalized conversation/message/item data.
frontend/src/pages/ProfilePage.js Replaces local date coalescing with centralized extractDate helper.
frontend/src/lib/utils.js Wraps normalizeItem for UI use; removes local category/date normalization and adds imageUrl fallback.

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment thread frontend/src/pages/Messages.js Outdated
Comment on lines +116 to +117
const aTime = a.lastMessageTime ? new Date(a.lastMessageTime).getTime() : 0;
const bTime = b.lastMessageTime ? new Date(b.lastMessageTime).getTime() : 0;
Copy link

Copilot AI Oct 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sort dropped the previous fallback to createdAt. If lastMessageTime is missing, conversations will sort as 0 and may appear out of order. Consider falling back to createdAt: compute time from lastMessageTime, or else from createdAt (both normalized ISO strings), before comparing.

Suggested change
const aTime = a.lastMessageTime ? new Date(a.lastMessageTime).getTime() : 0;
const bTime = b.lastMessageTime ? new Date(b.lastMessageTime).getTime() : 0;
const aTime = a.lastMessageTime
? new Date(a.lastMessageTime).getTime()
: (a.createdAt ? new Date(a.createdAt).getTime() : 0);
const bTime = b.lastMessageTime
? new Date(b.lastMessageTime).getTime()
: (b.createdAt ? new Date(b.createdAt).getTime() : 0);

Copilot uses AI. Check for mistakes.
Comment thread frontend/src/lib/utils.js
Comment on lines +41 to 47
...normalized,
// Override imageUrl default if it's empty
imageUrl: normalized.imageUrl || DEFAULT_IMAGE_URL,
// Add UI-specific fields
reporter,
claimed,
claimedAt,
claimedBy,
coordinates,
};
Copy link

Copilot AI Oct 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This refactor removes the previous category normalization (e.g., 'keys/cards' -> 'keys-cards', 'accessories' -> 'accessory'), changing the API shape that UI code may rely on for filtering/styling. Either re-apply the mapping here (post-normalization) or move it into normalizeItem so that all consumers receive consistent, normalized category values.

Copilot uses AI. Check for mistakes.
Comment thread frontend/src/pages/ProfilePage.js Outdated
Comment on lines +14 to +16
// REFACTORED: Replaced coalesceDate with extractDate from firestoreNormalizer
// This provides consistent date handling across the entire app
const coalesceDate = (item) => extractDate(item) || item.date || new Date().toISOString()
Copy link

Copilot AI Oct 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback item.date may be a Firestore Timestamp object, causing coalesceDate to return mixed types (ISO string vs object). Use normalizeTimestamp for the fallback (and import it) or drop the raw fallback to ensure a consistent ISO string return type.

Copilot uses AI. Check for mistakes.
// Firestore snapshot with .seconds property
if (value.seconds !== undefined) {
try {
return new Date(value.seconds * 1000).toISOString();
Copy link

Copilot AI Oct 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] When converting Firestore timestamp objects, include nanoseconds to avoid precision loss for ordering: new Date(value.seconds * 1000 + Math.floor((value.nanoseconds || 0) / 1e6)).toISOString().

Suggested change
return new Date(value.seconds * 1000).toISOString();
return new Date(value.seconds * 1000 + Math.floor((value.nanoseconds || 0) / 1e6)).toISOString();

Copilot uses AI. Check for mistakes.
Comment thread frontend/src/lib/utils.js
Comment on lines +41 to 47
...normalized,
// Override imageUrl default if it's empty
imageUrl: normalized.imageUrl || DEFAULT_IMAGE_URL,
// Add UI-specific fields
reporter,
claimed,
claimedAt,
claimedBy,
coordinates,
};
Copy link

Copilot AI Oct 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Previously this wrapper defaulted location to 'Unknown' for UI display; now missing locations will be an empty string (normalizeItem returns ''), while the error path still sets 'Unknown'. For consistent UI, consider adding location: normalized.location || 'Unknown' here.

Copilot uses AI. Check for mistakes.
@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Collaborator

@Embers2512 Embers2512 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything looks great, the test works properly and good job on removing the code duplication across the codebase. Your comments are immensely helpful for me to understand, good job 👍

@Embers2512 Embers2512 merged commit 77c04d6 into Softeng310:main Oct 19, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Refactor]: Code Refactor

3 participants