Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
08603d6
Initial plan
Copilot Nov 19, 2025
65448ef
Add user profile navigation: routes, components, and GraphQL updates
Copilot Nov 19, 2025
421e2be
Update message thread with clickable avatars and add Storybook stories
Copilot Nov 19, 2025
9c7110f
Add documentation for user profile navigation pattern
Copilot Nov 19, 2025
713735d
Merge branch 'main' into copilot/add-navigation-to-user-profile
dani-vaibhav Nov 28, 2025
7ab4250
fix: address code review feedback for user profile navigation components
Copilot Nov 28, 2025
455f446
feat: add user profile navigation and improve component imports
dani-vaibhav Nov 28, 2025
4223712
fix: update package.json to include node-forge dependency
dani-vaibhav Dec 1, 2025
13158b7
Merge branch 'main' into copilot/add-navigation-to-user-profile
dani-vaibhav Dec 1, 2025
c18136a
Merge branch 'main' into copilot/add-navigation-to-user-profile
dani-vaibhav Dec 1, 2025
8a6b7f1
fix: address code review feedback - fix layout component, user names …
Copilot Dec 2, 2025
907cf42
Merge branch 'main' into copilot/add-navigation-to-user-profile
dani-vaibhav Dec 2, 2025
af00807
Merge branch 'main' into copilot/add-navigation-to-user-profile
dani-vaibhav Dec 3, 2025
aeaeb52
Merge branch 'main' into copilot/add-navigation-to-user-profile
dani-vaibhav Dec 5, 2025
ebcf82d
Fix : Build error issue
dani-vaibhav Dec 5, 2025
ffdd263
refactor: address code review feedback - add JSDoc, extract shared ut…
Copilot Dec 5, 2025
485ceb4
Merge branch 'main' into copilot/add-navigation-to-user-profile
dani-vaibhav Dec 10, 2025
427e6f8
feat: add MemoryRouter decorator to ListingBanner story
dani-vaibhav Dec 10, 2025
ca60e45
fix: reorder import statements in ListingBanner story
dani-vaibhav Dec 10, 2025
cc89d8d
test: Add comprehensive test coverage for UI components
dani-vaibhav Dec 10, 2025
e5fbc1f
test: cover reservation request pagination logic
dani-vaibhav Dec 12, 2025
6f34240
Merge branch 'main' into copilot/add-navigation-to-user-profile
dani-vaibhav Dec 12, 2025
0a903d9
fix: update type assertions in ListingBanner stories and improve erro…
dani-vaibhav Dec 15, 2025
15b61d8
refactor: simplify type exports in sharer information, user avatar, a…
dani-vaibhav Dec 15, 2025
5bbd98f
feat: add user profile navigation and storybook examples for user pro…
dani-vaibhav Dec 16, 2025
6fa5d35
fix: address sourcery-ai feedback - clarify validation function, fix …
Copilot Dec 18, 2025
3930eed
fix: address final sourcery-ai feedback - clarify comment and add use…
Copilot Dec 18, 2025
599c4d0
refactor: centralize user profile routes and optimize conversation bo…
Copilot Dec 18, 2025
58fe3ba
fix: add fallback for broken avatar images with onError handler
Copilot Dec 18, 2025
9d3e31b
Merge branch 'main' into copilot/add-navigation-to-user-profile
dani-vaibhav Dec 18, 2025
f624fec
fix: improve error handling in startServer function and update integr…
dani-vaibhav Dec 19, 2025
7791056
Merge branch 'main' into copilot/add-navigation-to-user-profile
dani-vaibhav Dec 19, 2025
ff941e7
refactor: address code review feedback - remove unnecessary utilities…
Copilot Dec 23, 2025
a2808c5
refactor: remove unnecessary userId guard in UserProfileViewContainer
Copilot Dec 23, 2025
0e011ad
Merge branch 'main' into copilot/add-navigation-to-user-profile
dani-vaibhav Dec 24, 2025
352f9cc
refactor: clarify required MessageThread props and remove unnecessary…
Copilot Dec 24, 2025
0a6e235
refactor: remove defensive null check for reservation period field
Copilot Dec 24, 2025
2672748
refactor: remove redundant userId defensive checks in listing-banner
Copilot Dec 24, 2025
20ccbfc
feat: add requestedById field to ListingRequestUiShape and update pag…
dani-vaibhav Dec 29, 2025
dc250e0
revert: restore original messaging-service-mock test logic (remove un…
dani-vaibhav Dec 29, 2025
1524845
feat: add requestedById field to ListingRequestData and implement use…
dani-vaibhav Dec 29, 2025
0226ec9
feat: enhance user profile link component to handle optional userId a…
dani-vaibhav Dec 29, 2025
df878c4
fix: render missing userId message in public profile view
dani-vaibhav Dec 30, 2025
0c27758
refactor: extract SharerInformation container and move query/mutation…
dani-vaibhav Jan 5, 2026
13742b6
feat: add navigation to user profile in UserAvatar component
dani-vaibhav Jan 5, 2026
eb4aa96
style: reformat HomeRoutes to match project formatting rules
dani-vaibhav Jan 5, 2026
a7b4bce
refactor: remove unused getUserDisplayName and use direct user displa…
dani-vaibhav Jan 5, 2026
becccd9
refactor: remove requestedById from ListingRequestData interface and …
dani-vaibhav Jan 5, 2026
91a69d9
refactor: clean up reservation-request resolver responsibilities
dani-vaibhav Jan 5, 2026
a090d9c
chore: override qs to 6.14.1 for audit
dani-vaibhav Jan 5, 2026
4983137
Merge branch 'main' into copilot/add-navigation-to-user-profile
dani-vaibhav Jan 5, 2026
a1acd49
refactor: simplify ListingRequestPageItem definition and usage
dani-vaibhav Jan 5, 2026
784983b
test: add unit tests for queryListingRequestsBySharerId functionality
dani-vaibhav Jan 6, 2026
48813ae
Merge branch 'main' into copilot/add-navigation-to-user-profile
dani-vaibhav Jan 7, 2026
318813f
feat(env): define ProcessEnv interface for environment variables
dani-vaibhav Jan 7, 2026
92a3a30
Merge branch 'main' into copilot/add-navigation-to-user-profile
dani-vaibhav Jan 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import { useQuery } from '@apollo/client/react';
import { useMutation, useQuery } from '@apollo/client/react';
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { SharerInformation } from './sharer-information.tsx';
import { SharerInformationContainerDocument } from '../../../../../../generated.tsx';
import {
CreateConversationDocument,
HomeConversationListContainerConversationsByUserDocument,
SharerInformationContainerDocument,
} from '../../../../../../generated.tsx';
import type {
CreateConversationMutation,
CreateConversationMutationVariables,
} from '../../../../../../generated.tsx';

interface SharerInformationContainerProps {
sharerId: string;
Expand All @@ -15,13 +25,74 @@ interface SharerInformationContainerProps {
export const SharerInformationContainer: React.FC<
SharerInformationContainerProps
> = ({ sharerId, listingId, isOwner, sharedTimeAgo, className, currentUserId }) => {
const [isMobile, setIsMobile] = useState(false);
const navigate = useNavigate();

const { data, loading, error } = useQuery(
SharerInformationContainerDocument,
{
variables: { sharerId },
},
);

const [createConversation, { loading: isCreating }] = useMutation<
CreateConversationMutation,
CreateConversationMutationVariables
>(CreateConversationDocument, {
refetchQueries: [
{
query: HomeConversationListContainerConversationsByUserDocument,
variables: { userId: currentUserId },
},
],
awaitRefetchQueries: true,
onCompleted: (data) => {
if (data.createConversation.status.success) {
navigate('/messages', {
state: {
selectedConversationId: data.createConversation.conversation?.id,
},
replace: false,
});
} else {
console.log(
'Failed to create conversation:',
data.createConversation.status.errorMessage,
);
}
},
onError: (error) => {
console.error('Error creating conversation:', error);
},
});

const handleMessageSharer = async (resolvedSharerId: string) => {
if (!currentUserId) {
return;
}

try {
await createConversation({
variables: {
input: {
listingId,
sharerId: resolvedSharerId,
reserverId: currentUserId,
},
},
});
} catch (error) {
console.error('Failed to create conversation:', error);
}
};

useEffect(() => {
const checkMobile = () => setIsMobile(window.innerWidth <= 600);
checkMobile();
window.addEventListener('resize', checkMobile);
return () => window.removeEventListener('resize', checkMobile);
}, []);

// If sharerId looks like a name (contains spaces or letters), use it directly
// Otherwise, try to query for user data
const isNameOnly =
Expand All @@ -41,6 +112,9 @@ export const SharerInformationContainer: React.FC<
sharedTimeAgo={sharedTimeAgo}
className={className}
currentUserId={currentUserId}
isCreating={isCreating}
isMobile={isMobile}
Copy link
Contributor

Choose a reason for hiding this comment

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

Confused on why isMobile is being passed down, can be checked at any level, doesnt seem needed to me.

onMessageSharer={() => handleMessageSharer(sharer.id)}
/>
);
}
Expand All @@ -66,6 +140,9 @@ export const SharerInformationContainer: React.FC<
sharedTimeAgo={sharedTimeAgo}
className={className}
currentUserId={currentUserId}
isCreating={isCreating}
isMobile={isMobile}
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here

onMessageSharer={() => handleMessageSharer(sharer.id)}
/>
);
};
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import type { Meta, StoryObj } from '@storybook/react';
import { expect, within, userEvent } from 'storybook/test';
import { SharerInformation } from './sharer-information.tsx';
import {
withMockApolloClient,
withMockRouter,
} from '../../../../../../test-utils/storybook-decorators.tsx';
import {
CreateConversationDocument,
HomeConversationListContainerConversationsByUserDocument,
} from '../../../../../../generated.tsx';
import { withMockRouter } from '../../../../../../test-utils/storybook-decorators.tsx';

const mockSharer = {
id: 'user-1',
Expand All @@ -21,50 +14,17 @@ const meta: Meta<typeof SharerInformation> = {
component: SharerInformation,
parameters: {
layout: 'padded',
apolloClient: {
mocks: [
{
request: {
query: CreateConversationDocument,
variables: {
input: {
listingId: '1',
sharerId: 'user-1',
reserverId: 'user-2',
},
},
},
result: {
data: {
createConversation: {
__typename: 'ConversationMutationResult',
status: { success: true, errorMessage: null },
conversation: { __typename: 'Conversation', id: 'conv-1' },
},
},
},
},
{
request: {
query: HomeConversationListContainerConversationsByUserDocument,
variables: { userId: 'user-2' },
},
result: {
data: {
conversationsByUser: [],
},
},
},
],
},
},
decorators: [withMockApolloClient, withMockRouter('/listing/1')],
decorators: [withMockRouter('/listing/1')],
args: {
sharer: mockSharer,
listingId: '1',
isOwner: false,
sharedTimeAgo: '2 days ago',
currentUserId: 'user-2',
isCreating: false,
isMobile: false,
onMessageSharer: () => undefined,
},
};

Expand Down Expand Up @@ -125,52 +85,10 @@ export const ClickMessageButton: Story = {
},
};

export const MessageButtonWithError: Story = {
parameters: {
apolloClient: {
mocks: [
{
request: {
query: CreateConversationDocument,
variables: () => true,
},
maxUsageCount: Number.POSITIVE_INFINITY,
result: {
data: {
createConversation: {
__typename: 'ConversationMutationResult',
status: { success: false, errorMessage: 'Failed to create' },
conversation: null,
},
},
},
},
{
request: {
query: HomeConversationListContainerConversationsByUserDocument,
variables: () => true,
},
maxUsageCount: Number.POSITIVE_INFINITY,
result: {
data: {
conversationsByUser: [],
},
},
},
],
},
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await expect(canvasElement).toBeTruthy();
const messageButton = canvas.queryByRole('button', { name: /Message/i });
if (messageButton) {
await userEvent.click(messageButton);
}
},
};

export const MobileView: Story = {
args: {
isMobile: true,
},
parameters: {
viewport: {
defaultViewport: 'mobile1',
Expand Down
Loading
Loading