Changed header menu
Added date fields to Job
This commit is contained in:
parent
781275e9a9
commit
7b457244ae
@ -328,7 +328,9 @@ const JobCreator = (props: JobCreator) => {
|
|||||||
company: company,
|
company: company,
|
||||||
summary: summary,
|
summary: summary,
|
||||||
title: jobTitle,
|
title: jobTitle,
|
||||||
requirements: jobRequirements || undefined
|
requirements: jobRequirements || undefined,
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date(),
|
||||||
};
|
};
|
||||||
setIsProcessing(true);
|
setIsProcessing(true);
|
||||||
const job = await apiClient.createJob(newJob);
|
const job = await apiClient.createJob(newJob);
|
||||||
|
@ -26,6 +26,7 @@ import {
|
|||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemButton,
|
ListItemButton,
|
||||||
|
SxProps,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { styled, useTheme } from '@mui/material/styles';
|
import { styled, useTheme } from '@mui/material/styles';
|
||||||
import {
|
import {
|
||||||
@ -256,14 +257,23 @@ const Header: React.FC<HeaderProps> = (props: HeaderProps) => {
|
|||||||
// Render desktop navigation with dropdowns
|
// Render desktop navigation with dropdowns
|
||||||
const renderDesktopNavigation = () => {
|
const renderDesktopNavigation = () => {
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
<Box sx={{ display: 'flex', width: "100%", alignItems: 'center', justifyContent: "space-between"}}>
|
||||||
{navigationItems.map((item) => {
|
{navigationItems.map((item, index) => {
|
||||||
const hasChildren = item.children && item.children.length > 0;
|
const hasChildren = item.children && item.children.length > 0;
|
||||||
const isActive = isCurrentPath(item) || hasActiveChild(item);
|
const isActive = isCurrentPath(item) || hasActiveChild(item);
|
||||||
|
// Default is centered for all menu items
|
||||||
|
let sx : SxProps = { justifycontent: "center"};
|
||||||
|
// First item ("Backstory") is left aligned
|
||||||
|
if (index === 0) {
|
||||||
|
sx = { marginRight: "auto" };
|
||||||
|
}
|
||||||
|
// If there is an Admin menu, it is on the far right
|
||||||
|
if (item.userTypes?.includes('admin')) {
|
||||||
|
sx = { marginLeft: "auto"};
|
||||||
|
}
|
||||||
if (hasChildren) {
|
if (hasChildren) {
|
||||||
return (
|
return (
|
||||||
<Box key={item.id}>
|
<Box key={item.id} sx={sx}>
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
onClick={(e) => handleDropdownOpen(e, item.id)}
|
onClick={(e) => handleDropdownOpen(e, item.id)}
|
||||||
endIcon={<KeyboardArrowDown />}
|
endIcon={<KeyboardArrowDown />}
|
||||||
@ -306,6 +316,7 @@ const Header: React.FC<HeaderProps> = (props: HeaderProps) => {
|
|||||||
sx={{
|
sx={{
|
||||||
backgroundColor: isActive ? 'action.selected' : 'transparent',
|
backgroundColor: isActive ? 'action.selected' : 'transparent',
|
||||||
color: isActive ? 'secondary.main' : 'primary.contrastText',
|
color: isActive ? 'secondary.main' : 'primary.contrastText',
|
||||||
|
...sx
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{item.icon && <Box sx={{ mr: 1, display: 'flex' }}>{item.icon}</Box>}
|
{item.icon && <Box sx={{ mr: 1, display: 'flex' }}>{item.icon}</Box>}
|
||||||
|
@ -45,7 +45,7 @@ const JobInfo: React.FC<JobInfoProps> = (props: JobInfoProps) => {
|
|||||||
if (!job) {
|
if (!job) {
|
||||||
return <Box>No user loaded.</Box>;
|
return <Box>No user loaded.</Box>;
|
||||||
}
|
}
|
||||||
|
console.log(job);
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
elevation={elevation}
|
elevation={elevation}
|
||||||
|
@ -60,8 +60,8 @@ const SettingsPage = () => (<BetaPage><Typography variant="h4">Settings</Typogra
|
|||||||
export const navigationConfig: NavigationConfig = {
|
export const navigationConfig: NavigationConfig = {
|
||||||
items: [
|
items: [
|
||||||
{ id: 'home', label: <BackstoryLogo />, path: '/', component: <HomePage />, userTypes: ['guest', 'candidate', 'employer'], exact: true, },
|
{ id: 'home', label: <BackstoryLogo />, path: '/', component: <HomePage />, userTypes: ['guest', 'candidate', 'employer'], exact: true, },
|
||||||
{ id: 'chat', label: 'Chat about a Candidate', path: '/chat', icon: <ChatIcon />, component: <CandidateChatPage />, userTypes: ['guest', 'candidate', 'employer',], },
|
{ id: 'job-analysis', label: 'Job Analysis', path: '/job-analysis', icon: <WorkIcon />, component: <JobAnalysisPage />, userTypes: ['guest', 'candidate', 'employer',], },
|
||||||
{
|
{ id: 'chat', label: 'Candidate Chat', path: '/chat', icon: <ChatIcon />, component: <CandidateChatPage />, userTypes: ['guest', 'candidate', 'employer',], }, {
|
||||||
id: 'candidate-menu', label: 'Tools', icon: <PersonIcon />, userTypes: ['candidate'], children: [
|
id: 'candidate-menu', label: 'Tools', icon: <PersonIcon />, userTypes: ['candidate'], children: [
|
||||||
{ id: 'candidate-dashboard', label: 'Dashboard', path: '/candidate/dashboard', icon: <DashboardIcon />, component: <CandidateDashboard />, userTypes: ['candidate'] },
|
{ id: 'candidate-dashboard', label: 'Dashboard', path: '/candidate/dashboard', icon: <DashboardIcon />, component: <CandidateDashboard />, userTypes: ['candidate'] },
|
||||||
{ id: 'candidate-profile', label: 'Profile', icon: <PersonIcon />, path: '/candidate/profile', component: <CandidateProfile />, userTypes: ['candidate'] },
|
{ id: 'candidate-profile', label: 'Profile', icon: <PersonIcon />, path: '/candidate/profile', component: <CandidateProfile />, userTypes: ['candidate'] },
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
import React, { createContext, useContext, useState, useCallback, useEffect, useRef } from 'react';
|
import React, { createContext, useContext, useState, useCallback, useEffect, useRef } from 'react';
|
||||||
import * as Types from '../types/types';
|
import * as Types from '../types/types';
|
||||||
import { ApiClient, CreateCandidateRequest, CreateEmployerRequest, GuestConversionRequest } from '../services/api-client';
|
import { ApiClient, CreateCandidateRequest, CreateEmployerRequest, GuestConversionRequest } from 'services/api-client';
|
||||||
import { formatApiRequest, toCamelCase } from '../types/conversion';
|
import { formatApiRequest, toCamelCase } from 'types/conversion';
|
||||||
|
|
||||||
// ============================
|
// ============================
|
||||||
// Enhanced Types and Interfaces
|
// Enhanced Types and Interfaces
|
||||||
|
@ -196,7 +196,6 @@ class ApiClient {
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
const apiResponse = parsePaginatedResponse<T>(data);
|
const apiResponse = parsePaginatedResponse<T>(data);
|
||||||
const extractedData = extractApiData(apiResponse);
|
const extractedData = extractApiData(apiResponse);
|
||||||
console.log("extracted", extractedData);
|
|
||||||
// Apply model-specific date conversion to array items if modelType is provided
|
// Apply model-specific date conversion to array items if modelType is provided
|
||||||
if (modelType && extractedData.data) {
|
if (modelType && extractedData.data) {
|
||||||
return {
|
return {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Generated TypeScript types from Pydantic models
|
// Generated TypeScript types from Pydantic models
|
||||||
// Source: src/backend/models.py
|
// Source: src/backend/models.py
|
||||||
// Generated on: 2025-06-09T15:19:57.985888
|
// Generated on: 2025-06-09T17:45:24.922154
|
||||||
// DO NOT EDIT MANUALLY - This file is auto-generated
|
// DO NOT EDIT MANUALLY - This file is auto-generated
|
||||||
|
|
||||||
// ============================
|
// ============================
|
||||||
@ -426,13 +426,6 @@ export interface ChromaDBGetResponse {
|
|||||||
umapEmbedding3D?: Array<number>;
|
umapEmbedding3D?: Array<number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Citation {
|
|
||||||
text: string;
|
|
||||||
source: string;
|
|
||||||
context: string;
|
|
||||||
relevance: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CreateCandidateRequest {
|
export interface CreateCandidateRequest {
|
||||||
email: string;
|
email: string;
|
||||||
username: string;
|
username: string;
|
||||||
@ -699,11 +692,14 @@ export interface Job {
|
|||||||
id?: string;
|
id?: string;
|
||||||
ownerId: string;
|
ownerId: string;
|
||||||
ownerType: "candidate" | "employer" | "guest";
|
ownerType: "candidate" | "employer" | "guest";
|
||||||
|
owner?: BaseUser;
|
||||||
title?: string;
|
title?: string;
|
||||||
summary?: string;
|
summary?: string;
|
||||||
company?: string;
|
company?: string;
|
||||||
description: string;
|
description: string;
|
||||||
requirements?: JobRequirements;
|
requirements?: JobRequirements;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface JobApplication {
|
export interface JobApplication {
|
||||||
@ -726,11 +722,14 @@ export interface JobFull {
|
|||||||
id?: string;
|
id?: string;
|
||||||
ownerId: string;
|
ownerId: string;
|
||||||
ownerType: "candidate" | "employer" | "guest";
|
ownerType: "candidate" | "employer" | "guest";
|
||||||
|
owner?: BaseUser;
|
||||||
title?: string;
|
title?: string;
|
||||||
summary?: string;
|
summary?: string;
|
||||||
company?: string;
|
company?: string;
|
||||||
description: string;
|
description: string;
|
||||||
requirements?: JobRequirements;
|
requirements?: JobRequirements;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
location: Location;
|
location: Location;
|
||||||
salaryRange?: SalaryRange;
|
salaryRange?: SalaryRange;
|
||||||
employmentType: "full-time" | "part-time" | "contract" | "internship" | "freelance";
|
employmentType: "full-time" | "part-time" | "contract" | "internship" | "freelance";
|
||||||
@ -1470,6 +1469,21 @@ export function convertInterviewScheduleFromApi(data: any): InterviewSchedule {
|
|||||||
endDate: new Date(data.endDate),
|
endDate: new Date(data.endDate),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Convert Job from API response, parsing date fields
|
||||||
|
* Date fields: createdAt, updatedAt
|
||||||
|
*/
|
||||||
|
export function convertJobFromApi(data: any): Job {
|
||||||
|
if (!data) return data;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...data,
|
||||||
|
// Convert createdAt from ISO string to Date
|
||||||
|
createdAt: new Date(data.createdAt),
|
||||||
|
// Convert updatedAt from ISO string to Date
|
||||||
|
updatedAt: new Date(data.updatedAt),
|
||||||
|
};
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Convert JobApplication from API response, parsing date fields
|
* Convert JobApplication from API response, parsing date fields
|
||||||
* Date fields: appliedDate, updatedDate
|
* Date fields: appliedDate, updatedDate
|
||||||
@ -1487,13 +1501,17 @@ export function convertJobApplicationFromApi(data: any): JobApplication {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Convert JobFull from API response, parsing date fields
|
* Convert JobFull from API response, parsing date fields
|
||||||
* Date fields: datePosted, applicationDeadline, featuredUntil
|
* Date fields: createdAt, updatedAt, datePosted, applicationDeadline, featuredUntil
|
||||||
*/
|
*/
|
||||||
export function convertJobFullFromApi(data: any): JobFull {
|
export function convertJobFullFromApi(data: any): JobFull {
|
||||||
if (!data) return data;
|
if (!data) return data;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...data,
|
...data,
|
||||||
|
// Convert createdAt from ISO string to Date
|
||||||
|
createdAt: new Date(data.createdAt),
|
||||||
|
// Convert updatedAt from ISO string to Date
|
||||||
|
updatedAt: new Date(data.updatedAt),
|
||||||
// Convert datePosted from ISO string to Date
|
// Convert datePosted from ISO string to Date
|
||||||
datePosted: new Date(data.datePosted),
|
datePosted: new Date(data.datePosted),
|
||||||
// Convert applicationDeadline from ISO string to Date
|
// Convert applicationDeadline from ISO string to Date
|
||||||
@ -1688,6 +1706,8 @@ export function convertFromApi<T>(data: any, modelType: string): T {
|
|||||||
return convertInterviewFeedbackFromApi(data) as T;
|
return convertInterviewFeedbackFromApi(data) as T;
|
||||||
case 'InterviewSchedule':
|
case 'InterviewSchedule':
|
||||||
return convertInterviewScheduleFromApi(data) as T;
|
return convertInterviewScheduleFromApi(data) as T;
|
||||||
|
case 'Job':
|
||||||
|
return convertJobFromApi(data) as T;
|
||||||
case 'JobApplication':
|
case 'JobApplication':
|
||||||
return convertJobApplicationFromApi(data) as T;
|
return convertJobApplicationFromApi(data) as T;
|
||||||
case 'JobFull':
|
case 'JobFull':
|
||||||
|
@ -28,7 +28,7 @@ class CandidateChat(Agent):
|
|||||||
CandidateChat Agent
|
CandidateChat Agent
|
||||||
"""
|
"""
|
||||||
|
|
||||||
agent_type: Literal["candidate_chat"] = "candidate_chat"
|
agent_type: Literal["candidate_chat"] = "candidate_chat" # type: ignore
|
||||||
_agent_type: ClassVar[str] = agent_type # Add this for registration
|
_agent_type: ClassVar[str] = agent_type # Add this for registration
|
||||||
|
|
||||||
system_prompt: str = system_message
|
system_prompt: str = system_message
|
||||||
|
@ -3236,6 +3236,7 @@ async def create_candidate_job(
|
|||||||
# Add required fields
|
# Add required fields
|
||||||
job.id = str(uuid.uuid4())
|
job.id = str(uuid.uuid4())
|
||||||
job.owner_id = current_user.id
|
job.owner_id = current_user.id
|
||||||
|
job.owner = current_user
|
||||||
|
|
||||||
await database.set_job(job.id, job.model_dump())
|
await database.set_job(job.id, job.model_dump())
|
||||||
|
|
||||||
|
@ -683,11 +683,14 @@ class Job(BaseModel):
|
|||||||
id: str = Field(default_factory=lambda: str(uuid.uuid4()))
|
id: str = Field(default_factory=lambda: str(uuid.uuid4()))
|
||||||
owner_id: str = Field(..., alias="ownerId")
|
owner_id: str = Field(..., alias="ownerId")
|
||||||
owner_type: UserType = Field(..., alias="ownerType")
|
owner_type: UserType = Field(..., alias="ownerType")
|
||||||
|
owner: Optional[BaseUser] = None
|
||||||
title: Optional[str]
|
title: Optional[str]
|
||||||
summary: Optional[str]
|
summary: Optional[str]
|
||||||
company: Optional[str]
|
company: Optional[str]
|
||||||
description: str
|
description: str
|
||||||
requirements: Optional[JobRequirements]
|
requirements: Optional[JobRequirements]
|
||||||
|
created_at: datetime = Field(..., alias="createdAt")
|
||||||
|
updated_at: datetime = Field(..., alias="updatedAt")
|
||||||
model_config = {
|
model_config = {
|
||||||
"populate_by_name": True # Allow both field names and aliases
|
"populate_by_name": True # Allow both field names and aliases
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user