Skip to content

Improve activity log UX and team membership sync#111

Merged
ChitkulLakshya merged 7 commits into
mainfrom
activitylog
Apr 20, 2026
Merged

Improve activity log UX and team membership sync#111
ChitkulLakshya merged 7 commits into
mainfrom
activitylog

Conversation

@ChitkulLakshya
Copy link
Copy Markdown
Collaborator

Summary

  • Improve Activity Log filtering and selector UX with transparent dropdowns, team/member icon rendering, and more reliable owner/member resolution.
  • Add resilient team membership synchronization between backend and Firestore, including lifecycle handling for create/join/leave/remove/delete/ownership transfer.
  • Harden local dev/runtime stability by aligning API/socket behavior, reducing duplicate sync traffic, and throttling Firestore task-stat writes under quota pressure.

Test plan

  • Open Activity Log and verify team dropdown shows owner teams with logos and transparent styling.
  • Select a team and member; confirm profile/details render correctly and filters apply.
  • Create a team and verify it appears in backend APIs and Firestore teams/users metadata.
  • Join/leave/remove/delete/transfer ownership flows and confirm Firestore owner/member fields update automatically.
  • Run app locally (frontend + backend) and verify API calls no longer fail due to token/project-id misconfiguration.

Improve local dev reliability by aligning API/socket base URLs,
reducing duplicate sync/session requests, and wiring frontend/backend
startup flow to avoid repeated connection failures.

Made-with: Cursor
Apply multi-color circular team emblems and align button/navbar styling
so team identity remains consistent across settings and people screens.

Made-with: Cursor
Throttle activity fetch bursts and improve data wiring for current user/team
context so activity filters receive stable owner and membership metadata.

Made-with: Cursor
Refine owner-only team selection, transparent selector styling, and member/profile
resolution so team and user analytics remain accurate and visually consistent.

Made-with: Cursor
Normalize owner/member fields and sync create/join events to Firestore user/team
documents so ownership and membership stay in sync across clients.

Made-with: Cursor
Add backend team lifecycle hooks for Firestore consistency (join/leave/remove/delete/
transfer) and fix Firebase Admin initialization plus client write throttling safeguards.

Made-with: Cursor
Copilot AI review requested due to automatic review settings April 20, 2026 15:08
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
zync Building Building Preview, Comment Apr 20, 2026 3:09pm

Copy link
Copy Markdown

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

This PR improves Activity Log/People/Settings UX and strengthens team membership synchronization between the backend and Firestore, while also stabilizing local development by separating socket base URLs and tuning sync/write behavior.

Changes:

  • Introduces SOCKET_BASE_URL and updates multiple socket.io clients/providers to use it with consistent transport/reconnect settings.
  • Improves Activity Log filtering UX (team/member selectors with logos) and adds more robust team/user resolution and Firestore team persistence syncing.
  • Adds backend-to-Firestore team lifecycle sync helpers and relaxes dev rate limits; updates dev script to run frontend+backend together.

Reviewed changes

Copilot reviewed 25 out of 26 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/services/taskSocketService.ts Switch tasks socket to SOCKET_BASE_URL and adjust transports/reconnect behavior.
src/services/chatSocketService.ts Switch chat socket to SOCKET_BASE_URL and adjust transports/reconnect behavior.
src/pages/ProjectDetails.tsx Uses SOCKET_BASE_URL for project socket connection with reconnect options.
src/lib/utils.ts Adds SOCKET_BASE_URL env resolution (dev/prod).
src/lib/team-logos.ts Reworks team logos into generated SVG icons + color palettes for consistent rendering.
src/lib/SocketIOProvider.ts Notes socket now uses SOCKET_BASE_URL + reconnect options.
src/hooks/useTeamPersistence.ts Adds normalization + upsert/sync helpers to keep Firestore team/user metadata aligned with backend.
src/hooks/useTaskPersistence.ts Adds throttling/fingerprinting/cooldown to reduce Firestore task-stat write pressure.
src/hooks/usePresence.ts Presence socket now uses SOCKET_BASE_URL with reconnection options.
src/hooks/useNotePresence.ts Note presence socket now uses SOCKET_BASE_URL.
src/hooks/use-user-sync.ts Adds dev gating and swallows backend-sync errors to keep dev UX stable.
src/hooks/use-activity-tracker.ts Avoids duplicate session start by reusing localStorage session id.
src/components/views/SettingsView.tsx UI styling updates + team rename UX adjustments and logo rendering.
src/components/views/PeopleView.tsx UI styling updates + team logo rendering in sidebar/team header.
src/components/views/JoinTeamDialog.tsx Passes joined team payload to Firestore sync when available.
src/components/views/DesktopView.tsx Throttles activity refetches, normalizes API responses, and passes richer team/user context into Activity Log.
src/components/views/CreateTeamDialog.tsx Aligns with backend create response shape and updates logo picker rendering.
src/components/views/ActivityLogView.tsx Major Activity Log filter UX + robust team/member resolution + Firestore sync from API payloads.
package.json npm run dev now runs frontend+backend concurrently.
package-lock.json Adds concurrently dependency.
backend/services/teamFirebaseSync.js New Firestore sync service for team lifecycle events (create/join/leave/remove/delete/transfer).
backend/services/firebaseAdmin.js New shared firebase-admin init helper for Firestore sync.
backend/routes/userRoutes.js Hardens /sync by requiring/deriving email and simplifying upsert handling.
backend/routes/teamRoutes.js Hooks Firestore sync into team lifecycle routes with guarded “runSync”.
backend/middleware/authMiddleware.js Centralizes firebase-admin init via shared helper + ADC fallback.
backend/index.js Adjusts rate limiting for dev vs production.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

};

const getFirestoreAdmin = () => {
if (firestoreInstance) return firestoreInstance;
if (!admin.apps.length) {
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
projectId: serviceAccount.project_id || process.env.VITE_FIREBASE_PROJECT_ID,
Comment on lines +88 to +91
// Coalesce frequent writes caused by rapid UI/state updates.
if (now - lastSavedAtRef.current < SAVE_DEBOUNCE_MS) {
return;
}
Comment on lines +1068 to +1077
<Select
value={selectedTeamId === 'all' ? undefined : selectedTeamId}
onValueChange={(v) => {
setSelectedTeamId(v);
if (v === 'all') {
setSelectedUserId(currentUserId || 'all');
} else {
setSelectedUserId('all');
}
}}
Comment on lines 1128 to +1130
<Select value={selectedUserId} onValueChange={setSelectedUserId}>
<SelectTrigger className="w-[140px] h-9 bg-white/5 border-white/10 text-[11px] text-text2">
<SelectValue placeholder="Select Member" />
<SelectTrigger className="w-[170px] h-9 bg-white/[0.04] border-white/20 text-[11px] text-text2 backdrop-blur-md hover:bg-white/[0.08]">
{selectedUserId !== 'all' && selectedMemberOption ? (
Comment on lines 15 to 27
const unsubscribe = auth.onAuthStateChanged(async (user) => {
if (user && !sessionIdRef.current) {
// DesktopView already owns session start.
// Reuse the persisted active session to avoid duplicate /sessions/start calls.
try {
const token = await user.getIdToken();
const res = await fetch(`${API_BASE_URL}/api/sessions/start`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({ userId: user.uid }),
});
if (res.ok) {
const session = await res.json();
sessionIdRef.current = session._id;
const raw = localStorage.getItem('currentSession');
if (raw) {
const parsed = JSON.parse(raw);
sessionIdRef.current = parsed?.id || null;
}
} catch (e) {
console.error("Failed to start session:", e);
} catch {
sessionIdRef.current = null;
}
Comment on lines +106 to +132
await setDoc(doc(db, "teams", team.id), {
name: team.name,
ownerId: team.ownerId,
leaderId: team.ownerId,
members: team.members,
inviteCode: team.inviteCode,
logoId: team.logoId || "rocket",
createdAt: team.createdAt || new Date().toISOString(),
updatedAt: new Date().toISOString(),
}, { merge: true });

if (team.ownerId) {
await setDoc(doc(db, "users", team.ownerId), {
uid: team.ownerId,
ownedTeamIds: arrayUnion(team.id),
teamMemberships: arrayUnion(team.id),
updatedAt: new Date().toISOString(),
}, { merge: true });
}

for (const memberId of team.members) {
await setDoc(doc(db, "users", memberId), {
uid: memberId,
teamMemberships: arrayUnion(team.id),
updatedAt: new Date().toISOString(),
}, { merge: true });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants