Skip to content

Conversation

@Avdhesh-Varshney
Copy link
Member

Pull Requests Review Criteria

Caution

PRs that fail to meet these review standards will be automatically flagged and may be rejected by maintainers.

  • Filled out this PR template properly
  • Did not commit directly to main
  • Limited commits (max 3–4 unless permitted by Admin/Mentors)
  • Added comments in complex parts of code

Describe the add-ons or changes you've made 📃

  • settings & home routes extended
  • optimize /me api calls
  • home page states managed
  • setup homepage navbar
  • migrate project v1 route module

@Avdhesh-Varshney Avdhesh-Varshney self-assigned this Jan 7, 2026
@Avdhesh-Varshney Avdhesh-Varshney added the enhancement New feature or request label Jan 7, 2026
@vercel
Copy link

vercel bot commented Jan 7, 2026

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

Project Deployment Review Updated (UTC)
code-a2z Ready Ready Preview, Comment Jan 7, 2026 7:07pm
code-a2z-server Ready Ready Preview, Comment Jan 7, 2026 7:07pm

@github-actions
Copy link

github-actions bot commented Jan 7, 2026

Thank you for submitting your pull request! We'll review it as soon as possible. For further communication, join our discord server https://discord.gg/tSqtvHUJzE.

@Avdhesh-Varshney Avdhesh-Varshney merged commit e2d6a23 into main Jan 7, 2026
9 checks passed
@Avdhesh-Varshney Avdhesh-Varshney deleted the avdhesh/project-page branch January 7, 2026 19:09
Copy link
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

This PR restructures the home page and project viewing experience by introducing a dedicated home page navbar, migrating the project module to a nested v1 route structure, and optimizing API calls to prevent unnecessary duplicate requests. The changes establish a clearer separation between the home feed and individual project pages while improving performance through better state management.

Key Changes:

  • Implemented a simplified home page navbar without authentication-dependent features
  • Migrated project module from /modules/project to /modules/home/modules/project/v1 with proper nested routing
  • Optimized /me API calls by adding ref-based tracking to prevent duplicate fetches on component remounts

Reviewed changes

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

Show a summary per file
File Description
client/src/shared/hooks/use-auth.ts Added ref tracking and user state check to prevent duplicate /me API calls
client/src/shared/components/organisms/navbar/index.tsx Simplified navbar to remove authentication features, theme toggle, and user menu
client/src/shared/components/organisms/navbar/hooks/index.ts Refactored navbar hooks to manage search state and keyboard shortcuts
client/src/shared/components/organisms/navbar/components/render-mobile-menu.tsx Simplified mobile menu to only show Write and Subscribe options
client/src/shared/components/organisms/navbar/components/render-menu.tsx Removed entire user profile menu component
client/src/shared/components/organisms/comments-wrapper/index.tsx Updated import path to reflect project module migration
client/src/shared/components/organisms/comments-wrapper/hooks/index.ts Enhanced comment fetching with reset functionality and project change detection
client/src/shared/components/organisms/comments-wrapper/components/comment-field.tsx Updated import path for SelectedProjectAtom
client/src/shared/components/organisms/comments-wrapper/components/comment-card.tsx Updated import path for SelectedProjectAtom
client/src/shared/components/molecules/searchbar/index.tsx Converted to forwardRef pattern with improved ref handling and keyboard event support
client/src/shared/components/atoms/typography/index.tsx Added support for dangerouslySetInnerHTML without rendering text prop
client/src/modules/settings/v1/hooks/index.ts Updated to use new settingsRoutes function name
client/src/modules/settings/routes/index.tsx Refactored settings routes with new constant structure and lazy loading
client/src/modules/settings/modules/index.tsx Added centralized lazy component exports for settings modules
client/src/modules/search/index.tsx Updated hook name from useHome to useHomeV1
client/src/modules/project/index.tsx Deleted old project component (migrated to new location)
client/src/modules/project/components/project-content.tsx Deleted old project content component (migrated to new location)
client/src/modules/profile/index.tsx Updated hook name from useHome to useHomeV1
client/src/modules/profile/hooks/index.ts Updated hook name from useHome to useHomeV1
client/src/modules/notification/components/notificationCard.tsx Updated project links to use ROUTES_V1.HOME constant
client/src/modules/manage-projects/components/publish-projects.tsx Updated project links to use ROUTES_V1.HOME constant
client/src/modules/home/v1/states/index.ts Removed unused state atoms (HomePageStateAtom, HomePageTrendingProjectsAtom)
client/src/modules/home/v1/index.tsx Added navbar, nested routing support, and improved project fetching logic
client/src/modules/home/v1/hooks/index.ts Refactored to support nested routing with isHomePage check and proper memoization
client/src/modules/home/v1/components/no-banner-project.tsx Migrated to use A2ZTypography and updated route constants
client/src/modules/home/v1/components/banner-project-card.tsx Migrated to use A2ZTypography and updated route constants
client/src/modules/home/routes/index.tsx Added new home routes configuration for nested project routing
client/src/modules/home/modules/project/v1/states/index.ts Fixed import path for ProjectData type
client/src/modules/home/modules/project/v1/index.tsx Migrated project component with improved external link handling and styling
client/src/modules/home/modules/project/v1/hooks/use-project-interaction.ts Simplified like handling by removing authentication check
client/src/modules/home/modules/project/v1/hooks/index.ts Added ref-based duplicate fetch prevention and reset functionality
client/src/modules/home/modules/project/v1/components/project-interaction.tsx Added module-level refs to prevent duplicate like status API calls
client/src/modules/home/modules/project/v1/components/project-content.tsx Migrated with A2ZTypography usage and improved theme-aware styling
client/src/modules/home/modules/index.tsx Added centralized lazy component exports for home modules
client/src/modules/app/routes/constants/routes.ts Restructured route constants into separate enums for better organization
client/src/modules/app/routes/auth-routes/v1/index.tsx Updated home route to support wildcard nested routing
Comments suppressed due to low confidence (2)

client/src/modules/home/modules/project/v1/components/project-interaction.tsx:61

  • The setLikedByUser dependency is missing from the useEffect dependency array. While the code uses setLikedByUser, it's not included in the dependencies on line 61. This violates React's exhaustive-deps rule.
    client/src/modules/home/modules/project/v1/components/project-interaction.tsx:19
  • The ref logic for preventing duplicate fetches should use a React ref (useRef) instead of a module-level object. Module-level refs are shared across all component instances, which could cause issues if multiple instances of this component are mounted. Consider using useRef within the component and passing it through context or lifting the state management to a parent component.

Comment on lines +59 to +64
useEffect(() => {
document.addEventListener('keydown', triggerSearchByKeyboard, true);
return () => {
document.removeEventListener('keydown', triggerSearchByKeyboard, true);
};
}, [isDesktop]);
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

The useEffect hook has a missing dependency. The triggerSearchByKeyboard function is referenced in the dependency array, but it's defined in the same file and recreated on every render. This could cause the effect to run more times than necessary. Consider wrapping triggerSearchByKeyboard in a useCallback hook or removing it from the dependencies if isDesktop is sufficient.

Copilot uses AI. Check for mistakes.
Comment on lines +30 to +47
const fetchLatestProjects = useCallback(
async (page = 1) => {
if (!isHomePage) return;
const response = await getAllProjects(page);
if (response.data) {
setProjects(response.data);
}
},
[setProjects]
);

const fetchTrendingProjects = async () => {
const fetchTrendingProjects = useCallback(async () => {
if (!isHomePage) return;
const response = await getTrendingProjects();
if (response.data) {
setTrending(response.data);
setTrendingProjects(response.data);
}
};
}, [setTrendingProjects]);
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

The isHomePage dependency is missing from the useCallback dependencies. The callback functions fetchLatestProjects, fetchTrendingProjects, and fetchProjectsByCategory all check isHomePage internally, so it should be included in their dependency arrays. Without it, these functions may use stale values of isHomePage.

Copilot uses AI. Check for mistakes.
Comment on lines +49 to +79
const fetchProjectsByCategory = useCallback(
async ({
tag,
query,
user_id,
page,
limit,
page = 1,
limit = 10,
rmv_project_by_id,
});
if (response.data) {
setProjects(response.data);
}
};
}: {
tag?: string;
query?: string;
user_id?: string;
page?: number;
limit?: number;
rmv_project_by_id?: string;
}) => {
if (!isHomePage) return;
const response = await searchProjects({
tag,
query,
user_id,
page,
limit,
rmv_project_by_id,
});
if (response.data) {
setProjects(response.data);
}
},
[setProjects]
);
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

The isHomePage dependency is missing from the useCallback dependencies. This function checks isHomePage internally but doesn't include it in the dependency array, which could lead to stale closure issues.

Copilot uses AI. Check for mistakes.
Comment on lines +28 to 41
// Only fetch user if we don't already have user data and haven't fetched yet
if (!user && !hasFetchedUserRef.current) {
hasFetchedUserRef.current = true;
try {
const response = await getCurrentUser();
if (response.status === 'success' && response.data) {
setUser(response.data);
}
} catch (error) {
// If fetching user fails, token might be invalid
// Don't clear token here - let the interceptor handle it
console.error('Failed to fetch current user:', error);
hasFetchedUserRef.current = false; // Allow retry on next mount if needed
}
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

The check hasFetchedUserRef.current in the condition will always allow the user fetch to happen on first mount since the ref starts as false. However, if the user atom already has data (e.g., from a previous session or hydration), this will still trigger an unnecessary API call. Consider also checking if user data already exists before making the API call: if (!user && !hasFetchedUserRef.current). This appears to be the intended behavior based on the comment, but it's worth verifying.

Copilot uses AI. Check for mistakes.
Comment on lines +6 to +18
export const homeRoutes = () => {
const routes: React.ReactNode[] = [
<Route
key={ROUTES_HOME_V1.PROJECT}
path={ROUTES_HOME_V1.PROJECT}
element={
<ProtectedRoute component={ProjectLazyComponentV1} hasAccess={true} />
}
/>,
];

return { routes };
};
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

The function is exported but lacks JSDoc documentation explaining its purpose, parameters, and return value. Consider adding documentation to describe what this function does, especially since it's a utility function that handles route configuration.

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +32
const HeaderBlock = ({ level, text }: { level: number; text: string }) => {
const variant = level === 3 ? 'h5' : 'h4';
const component = level === 3 ? 'h3' : 'h2';
return (
<A2ZTypography
variant={variant}
component={component}
text=""
props={{
dangerouslySetInnerHTML: { __html: text },
sx: { fontWeight: 600, mb: 2, mt: 3 },
}}
/>
);
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

Similar to the ParagraphBlock, using text="" with dangerouslySetInnerHTML is unnecessary. Omit the text prop when using dangerouslySetInnerHTML.

Copilot uses AI. Check for mistakes.
Comment on lines +118 to +127
{items.map((item, i) => (
<li key={i}>
<A2ZTypography
variant="body1"
text=""
props={{
dangerouslySetInnerHTML: { __html: item },
}}
/>
</li>
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

Using text="" with dangerouslySetInnerHTML is redundant. Omit the text prop when using dangerouslySetInnerHTML.

Copilot uses AI. Check for mistakes.
Comment on lines +75 to 87
const handleClearClick = () => {
handleOnClearClick();
// Focus the input after clearing
setTimeout(() => {
const refToUse = inputRef || ref || internalInputRef;
if (
refToUse &&
typeof refToUse === 'object' &&
'current' in refToUse &&
refToUse.current
) {
refToUse.current.focus();
}
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

The ref handling logic is complex and could be simplified. The code attempts to handle three different ref sources (inputRef, ref, and internalInputRef) and checks if they're objects with a 'current' property. This is overly complex. Consider using a single ref approach by forwarding the ref properly through the component, or simplify the ref merging logic.

Suggested change
const handleClearClick = () => {
handleOnClearClick();
// Focus the input after clearing
setTimeout(() => {
const refToUse = inputRef || ref || internalInputRef;
if (
refToUse &&
typeof refToUse === 'object' &&
'current' in refToUse &&
refToUse.current
) {
refToUse.current.focus();
}
const focusInput = () => {
const possibleRefs = [inputRef, ref, internalInputRef];
for (const candidate of possibleRefs) {
if (
candidate &&
typeof candidate === 'object' &&
'current' in candidate &&
candidate.current
) {
candidate.current.focus();
return;
}
}
};
const handleClearClick = () => {
handleOnClearClick();
// Focus the input after clearing
setTimeout(() => {
focusInput();

Copilot uses AI. Check for mistakes.
Comment on lines +6 to +16
const ParagraphBlock = ({ text }: { text: string }) => {
return (
<A2ZTypography
variant="body1"
text=""
props={{
dangerouslySetInnerHTML: { __html: text },
sx: { lineHeight: 1.8 },
}}
/>
);
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

The empty text="" prop passed to A2ZTypography when using dangerouslySetInnerHTML is unnecessary and could be confusing. When using dangerouslySetInnerHTML, you should omit the text prop entirely since it won't be used. This makes the component's API clearer.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants