feat: implement hiring management platform and resolve repository compilation type errors#149
feat: implement hiring management platform and resolve repository compilation type errors#149Itzzavdheshh wants to merge 9 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive client-side hiring platform feature, including a jobs dashboard, job creation wizard, applicants tracking board, email sender, media gallery, moderation queue, and public-facing career portals. Feedback on these changes focuses on optimizing performance and reliability: filtering jobs and applicants in memory using useMemo to eliminate query delays on search keystrokes, accessing the Zustand store directly inside query functions to prevent stale closures, and dynamically resolving job titles instead of hardcoding them. Additionally, reviewers recommend persisting draft jobs to the store upon saving, avoiding QuotaExceededError crashes from storing large base64 images in localStorage, making risk checks case-insensitive, and correcting capitalized state variable names to follow standard camelCase conventions.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| export function useApplicants(jobId: string | undefined, search?: string, status?: string) { | ||
| const applicants = useHiringStore((state) => state.applicants); | ||
|
|
||
| return useQuery({ | ||
| queryKey: ["hiring-applicants", jobId, search, status], | ||
| queryFn: async () => { | ||
| await delay(400); | ||
| let list = applicants.filter((a) => a.jobId === jobId); | ||
|
|
||
| if (search) { | ||
| const q = search.toLowerCase(); | ||
| list = list.filter( | ||
| (a) => | ||
| a.name.toLowerCase().includes(q) || | ||
| a.email.toLowerCase().includes(q) || | ||
| a.skills.some((s) => s.toLowerCase().includes(q)) | ||
| ); | ||
| } | ||
|
|
||
| if (status && status !== "all") { | ||
| if (status === "strong") { | ||
| list = list.filter((a) => a.matchScore >= 85); | ||
| } else { | ||
| list = list.filter((a) => a.status === status); | ||
| } | ||
| } | ||
|
|
||
| return list; | ||
| }, | ||
| enabled: !!jobId, | ||
| }); | ||
| } |
There was a problem hiding this comment.
Simplify the useApplicants hook to only fetch applicants by jobId from the Zustand store state using useHiringStore.getState(). This allows the client-side pages to perform search and tab filtering in memory, avoiding a 400ms delay on every single keystroke in the search input.
export function useApplicants(jobId: string | undefined) {
return useQuery({
queryKey: ["hiring-applicants", jobId],
queryFn: async () => {
await delay(400);
return useHiringStore.getState().applicants.filter((a) => a.jobId === jobId);
},
enabled: !!jobId,
});
}| const { data: applicants = [], isLoading } = useApplicants(jobId, search, activeTab === "all" ? undefined : activeTab); | ||
| const updateStatusMutation = useUpdateApplicantStatus(); | ||
|
|
||
| // Metrics (dynamically computed from all applicants for this job) | ||
| const allJobApplicants = useApplicants(jobId).data || []; |
There was a problem hiding this comment.
Instead of passing search and activeTab filters to the useApplicants hook (which triggers a new query with a 400ms delay on every single keystroke), fetch all applicants for the job once and filter them in memory using useMemo. This also eliminates the redundant second hook call on line 26.
const { data: allApplicants = [], isLoading } = useApplicants(jobId);
const updateStatusMutation = useUpdateApplicantStatus();
const allJobApplicants = allApplicants;
const applicants = useMemo(() => {
return allApplicants.filter((a) => {
if (search) {
const q = search.toLowerCase();
const matchesSearch =
a.name.toLowerCase().includes(q) ||
a.email.toLowerCase().includes(q) ||
a.skills.some((s) => s.toLowerCase().includes(q));
if (!matchesSearch) return false;
}
if (activeTab !== "all") {
if (activeTab === "strong") {
return a.matchScore >= 85;
}
return a.status === activeTab;
}
return true;
});
}, [allApplicants, search, activeTab]);
| @@ -0,0 +1,471 @@ | |||
| import { useState } from "react"; | |||
| @@ -0,0 +1,401 @@ | |||
| import { useState } from "react"; | |||
| const valid = isValidDomain(domain); | ||
| const [Domain, setDomain] = React.useState(domain); | ||
| const valid = isValidDomain(domain || ""); | ||
| const [Domain, setDomain] = React.useState(domain || ""); |
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
|
Add image |
Summary
This PR implements a modern, scalable, production-grade Hiring Management Platform ("CommDesk") under
src/features/Hiring/v1/. It also cleans up several pre-existing unused imports/locals and resolves common component type mismatches, successfully enabling a clean production build (npm run buildwithnoUnusedLocals: true):localStoragepre-seeded with realistic candidate details./company/:slugand/company/:slug/jobs/:jobIdenabling guests to view profile details and submit real-time applications directly into the organization's backend candidate queue.Urlinput component where anundefineddomain prop caused strict type check exceptions.Related Issue
Fixes #121
Type of Change
Changes Implemented
src/features/Hiring/v1/:Types/Hiring.types.ts: Defined standard interfaces forJobRole,Applicant,CompanyProfile,MailLog, andAuditLog.Store/hiringStore.ts: Configured Zustand storage with persistence and mock data.Hooks/useHiring.ts: Added React Query wrappers for client-side API behavior.Pages/*: Created all operational views (Dashboard, Create/Edit Steppers, Applicants list, ATS Details, Send Mail, Company Profile Branding, and Media).src/Component/ui/Url.tsx:string | undefinedvsstringparameter constraint).PublicCompanyProfilePage.tsx&PublicJobDetailsPage.tsx(removed unused imports).Administrative_MetaData.tsx&MemberShip_Status.tsx(removed unused imports).ProfessionalDetails.tsx(removed unusedgetSkillColorand its import).MemberLayout.tsx(removed unusedHeaderimport).OrgRoute.tsx,MemberRoutes.tsx, &SideBar.tsx:Technical Details
Frontend
Backend
Database
localStorage.API
Infrastructure
Screenshots
Before
string | undefinedparameters in legacy files.After
npm run build) and type check (npx tsc --noEmit) complete successfully in under 25 seconds.Testing
Unit Tests
Integration Tests
E2E Tests
Manual Testing
/company/nexgen-studiospaths.Security Review
localStoragereading/writing with safety try-catch wrappers to prevent crashing in SSR rendering environments.Accessibility Review
header,main), key descriptors, and alt properties on dynamic images.Performance Impact
Breaking Changes
Deployment Notes
Rollback Plan
Checklist