Skip to content

Commit e57d9c4

Browse files
authored
Merge pull request #468 from Vandivier/462-job-search-entity
feat: job search entity
2 parents ed8335e + 2bd45e0 commit e57d9c4

21 files changed

+2182
-104
lines changed

ladderly-io/prisma/schema.prisma

+101
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ model User {
5353
5454
accounts Account[]
5555
authoredVotables Votable[] @relation("AuthoredVotables")
56+
jobSearches JobSearch[]
5657
quizResults QuizResult[]
5758
role RoleEnum @default(USER)
5859
sessions Session[]
@@ -382,3 +383,103 @@ model Lead {
382383
383384
@@index([userId])
384385
}
386+
387+
// Job Search Models
388+
enum JobApplicationStatus {
389+
IN_OUTREACH
390+
APPLIED
391+
IN_INTERVIEW
392+
REJECTED
393+
OFFER_RECEIVED
394+
TIMED_OUT
395+
WITHDRAWN
396+
}
397+
398+
model JobSearch {
399+
id Int @id @default(autoincrement())
400+
createdAt DateTime @default(now())
401+
updatedAt DateTime @updatedAt
402+
name String
403+
startDate DateTime @default(now())
404+
endDate DateTime?
405+
isActive Boolean @default(true)
406+
notes String?
407+
408+
// Relations
409+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
410+
userId Int
411+
jobPosts JobPostForCandidate[]
412+
}
413+
414+
model JobPostForCandidate {
415+
id Int @id @default(autoincrement())
416+
createdAt DateTime @default(now())
417+
updatedAt DateTime @updatedAt
418+
419+
// Company info
420+
company String
421+
jobTitle String?
422+
jobPostUrl String?
423+
jobBoardOrChannelName String?
424+
425+
// Application info
426+
resumeVersion String?
427+
initialOutreachDate DateTime?
428+
initialApplicationDate DateTime?
429+
lastActionDate DateTime?
430+
status JobApplicationStatus
431+
432+
// Contact info
433+
contactName String?
434+
contactUrl String?
435+
hasReferral Boolean
436+
437+
// Outreach tracking
438+
isInboundOpportunity Boolean
439+
440+
// Compensation
441+
baseSalary Int?
442+
totalCompensation Int?
443+
444+
// Misc
445+
notes String?
446+
447+
// Relations
448+
jobSearch JobSearch @relation(fields: [jobSearchId], references: [id], onDelete: Cascade)
449+
jobSearchId Int
450+
jobSearchSteps JobSearchStep[]
451+
}
452+
453+
enum JobSearchStepKind {
454+
BACKGROUND_OR_REFERENCE_CHECK
455+
BEHAVIORAL_INTERVIEW
456+
HIRING_MANAGER_CALL
457+
INITIAL_APPLICATION
458+
MULTI_ROUND_MULTI_KIND // eg a final loop
459+
NONTECHNICAL_CONVERSATION
460+
OTHER
461+
OUTBOUND_MESSAGE
462+
PHONE_SCREEN
463+
SYSTEM_DESIGN
464+
TAKE_HOME_ASSIGNMENT
465+
TECHNICAL_CODE_SCREEN_AUTOMATED
466+
TECHNICAL_CODE_SCREEN_MANUAL
467+
TECHNICAL_CONVERSATION
468+
TECHNICAL_OTHER
469+
}
470+
471+
model JobSearchStep {
472+
id Int @id @default(autoincrement())
473+
createdAt DateTime @default(now())
474+
updatedAt DateTime @updatedAt
475+
476+
date DateTime
477+
kind JobSearchStepKind
478+
notes String?
479+
isPassed Boolean?
480+
isInPerson Boolean
481+
482+
// Relations
483+
jobPost JobPostForCandidate @relation(fields: [jobPostId], references: [id], onDelete: Cascade)
484+
jobPostId Int
485+
}

ladderly-io/public/sitemap.xml

+5
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@
169169
https://ladderly.io/forgot-password
170170
</loc>
171171
</url>
172+
<url>
173+
<loc>
174+
https://ladderly.io/job-search
175+
</loc>
176+
</url>
172177
<url>
173178
<loc>
174179
https://ladderly.io/login

ladderly-io/scripts/python/copilot-instructions.txt

+15
Original file line numberDiff line numberDiff line change
@@ -416,8 +416,22 @@ src\app\home/
416416
HomePageSkeleton.tsx
417417
LadderlyHelpsBlock.tsx
418418
TestimonialBlock.tsx
419+
src\app\job-search/
420+
CreateJobSearchModal.tsx
421+
JobSearchActiveSpan.tsx
422+
JobSearchList.tsx
423+
page.tsx
424+
src\app\job-search\job-post/
425+
src\app\job-search\job-post\[id]/
426+
JobPostDetails.tsx
427+
page.tsx
428+
src\app\job-search\[id]/
429+
AddJobApplicationModal.tsx
430+
JobSearchDetails.tsx
431+
page.tsx
419432
src\app\mobile-menu/
420433
MobileMenuContent.tsx
434+
MobileMenuDropdowns.tsx
421435
page.tsx
422436
src\app\perks/
423437
page.tsx
@@ -448,6 +462,7 @@ src\server\api\routers/
448462
auth.ts
449463
chat.ts
450464
checklist.ts
465+
jobSearch.ts
451466
post.ts
452467
user.ts
453468
src\server\mailers/

ladderly-io/src/app/copilot/page.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const LadderlyCopilotPage = () => {
1616
<iframe
1717
src="https://www.chatbase.co/chatbot-iframe/NnbDY2pCxZROnVKZwpjaW"
1818
width="100%"
19-
style={{ height: '100%', minHeight: '700px' }}
19+
style={{ height: '100%', minHeight: '700px', borderRadius: '8px' }}
2020
></iframe>
2121
</div>
2222
</LadderlyPageWrapper>

ladderly-io/src/app/core/components/page-wrapper/MenuProvider.tsx

+15
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,18 @@ export const MenuProvider: React.FC<{ children: React.ReactNode }> = ({
2929
</MenuContext.Provider>
3030
)
3131
}
32+
33+
export const MenuItemsWrapper = ({
34+
children,
35+
}: {
36+
children: React.ReactNode
37+
}) => (
38+
<div
39+
className="ml-auto flex flex-wrap py-1"
40+
role="menu"
41+
aria-orientation="vertical"
42+
aria-labelledby="options-menu"
43+
>
44+
{children}
45+
</div>
46+
)

ladderly-io/src/app/core/components/page-wrapper/TopNavRight.tsx

+21-27
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import { MenuContext } from './MenuProvider'
88
import {
99
AccountMenuItems,
1010
CommunityMenuItems,
11+
GrowMenuItems,
1112
TOP_NAV_STANDARD_CLASSES,
12-
// TopHonorsMenuItems,
1313
} from './TopNavSubmenu'
1414

1515
const TOP_NAV_RIGHT_SECTION_CLASSES = 'ml-auto flex items-center space-x-6'
@@ -35,6 +35,18 @@ export const TopNavRight = () => {
3535
}
3636
}, [searchParams, currentUserQuery, router])
3737

38+
const handleAccountClick = (e: React.MouseEvent<HTMLButtonElement>) => {
39+
e.preventDefault()
40+
if (openMenuName === 'account') {
41+
setMenu?.(null, '')
42+
} else if (currentUser) {
43+
setMenu?.(
44+
<AccountMenuItems userId={currentUser.id.toString()} />,
45+
'account',
46+
)
47+
}
48+
}
49+
3850
const handleCommunityClick = (e: React.MouseEvent<HTMLButtonElement>) => {
3951
e.preventDefault()
4052
if (openMenuName === 'community') {
@@ -44,45 +56,27 @@ export const TopNavRight = () => {
4456
}
4557
}
4658

47-
const handleAccountClick = (e: React.MouseEvent<HTMLButtonElement>) => {
59+
const handleGrowClick = (e: React.MouseEvent<HTMLButtonElement>) => {
4860
e.preventDefault()
49-
if (openMenuName === 'account') {
61+
if (openMenuName === 'grow') {
5062
setMenu?.(null, '')
51-
} else if (currentUser) {
52-
setMenu?.(
53-
<AccountMenuItems userId={currentUser.id.toString()} />,
54-
'account',
55-
)
63+
} else {
64+
setMenu?.(<GrowMenuItems />, 'grow')
5665
}
5766
}
5867

59-
// const handleLeaderboardClick = (e: React.MouseEvent<HTMLButtonElement>) => {
60-
// e.preventDefault();
61-
// if (openMenuName === "leaderboard") {
62-
// setMenu(null, "");
63-
// } else {
64-
// setMenu(<TopHonorsMenuItems />, "leaderboard");
65-
// }
66-
// };
67-
6868
return (
6969
<div className={TOP_NAV_RIGHT_SECTION_CLASSES}>
70-
{/* <button
71-
onClick={handleLeaderboardClick}
72-
className={TOP_NAV_STANDARD_CLASSES}
73-
>
74-
Top Honors Leaderboard
75-
<IconVerticalChevron isPointingUp={openMenuName === "leaderboard"} />
76-
</button> */}
7770
<Link href="/perks" className={TOP_NAV_STANDARD_CLASSES}>
7871
Perks
7972
</Link>
8073
<Link href="/chat" className={TOP_NAV_STANDARD_CLASSES}>
8174
Chat
8275
</Link>
83-
<Link href="/blog" className={TOP_NAV_STANDARD_CLASSES}>
84-
Blog
85-
</Link>
76+
<button onClick={handleGrowClick} className={TOP_NAV_STANDARD_CLASSES}>
77+
Grow
78+
<IconVerticalChevron isPointingUp={openMenuName === 'grow'} />
79+
</button>
8680
<button
8781
onClick={handleCommunityClick}
8882
className={TOP_NAV_STANDARD_CLASSES}

ladderly-io/src/app/core/components/page-wrapper/TopNavSubmenu.tsx

+19-12
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { signOut } from 'next-auth/react'
44
import Link from 'next/link'
55
import React from 'react'
66

7-
import { MenuContext } from './MenuProvider'
7+
import { MenuContext, MenuItemsWrapper } from './MenuProvider'
88

99
export const TOP_NAV_STANDARD_CLASSES = 'ml-6 font-bold'
1010
export const MENU_ITEM_STANDARD_CLASSES =
@@ -30,17 +30,6 @@ export const AccountMenuItems = ({
3030
</MenuItemsWrapper>
3131
) : null
3232

33-
const MenuItemsWrapper = ({ children }: { children: React.ReactNode }) => (
34-
<div
35-
className="ml-auto flex flex-wrap py-1"
36-
role="menu"
37-
aria-orientation="vertical"
38-
aria-labelledby="options-menu"
39-
>
40-
{children}
41-
</div>
42-
)
43-
4433
export const CommunityMenuItems = ({
4534
linkClassName = DESKTOP_MENU_ITEM_STANDARD_CLASSES,
4635
}: {
@@ -60,6 +49,24 @@ export const CommunityMenuItems = ({
6049
</MenuItemsWrapper>
6150
)
6251

52+
export const GrowMenuItems = ({
53+
linkClassName = DESKTOP_MENU_ITEM_STANDARD_CLASSES,
54+
}: {
55+
linkClassName?: string
56+
}) => (
57+
<MenuItemsWrapper>
58+
<Link href="/blog" className={linkClassName}>
59+
Blog
60+
</Link>
61+
<Link href="/copilot" className={linkClassName}>
62+
Copilot
63+
</Link>
64+
<Link href="/job-search" className={linkClassName}>
65+
Job Search
66+
</Link>
67+
</MenuItemsWrapper>
68+
)
69+
6370
const LogoutButton = ({ className }: { className: string }) => {
6471
const { setMenu } = React.useContext(MenuContext)
6572

ladderly-io/src/app/home/HomePageContent.tsx

-4
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,6 @@ const HomePageContent = ({ session }: { session: LadderlySession | null }) => (
6464
>
6565
Read the announcement
6666
</Link>
67-
or
68-
<Link className="mx-2 font-bold underline" href="/copilot">
69-
chat now!
70-
</Link>
7167
</h2>
7268
</div>
7369
<main style={{ padding: '0rem 1rem' }}>

0 commit comments

Comments
 (0)