Skip to content

Commit

Permalink
make offer count work (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
januschung authored Dec 16, 2024
1 parent 99b9bce commit bd05c57
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 29 deletions.
4 changes: 2 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import JobApplicationList from './components/JobApplicationList';
import CssBaseline from '@mui/material/CssBaseline';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import PrimarySearchAppBar from './components/PrimarySearchAppBar';
import AppHeader from './components/AppHeader';
import { Route, Routes } from "react-router-dom"

const theme = createTheme();
Expand All @@ -11,7 +11,7 @@ function App() {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<PrimarySearchAppBar/>
<AppHeader/>
<div className="App">
</div>
</ThemeProvider>
Expand Down
8 changes: 4 additions & 4 deletions src/App.test.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import App from './App';
import PrimarySearchAppBar from './components/PrimarySearchAppBar';
import AppHeader from './components/AppHeader';
import JobApplicationList from './components/JobApplicationList';


jest.mock('./components/PrimarySearchAppBar')
jest.mock('./components/AppHeader')
jest.mock('./components/JobApplicationList')

it('Should render Job Application list on default route', async () => {
PrimarySearchAppBar.mockImplementation(() => <div>PrimarySearchAppBarMock</div>)
AppHeader.mockImplementation(() => <div>AppHeaderMock</div>)
JobApplicationList.mockImplementation(() => <div>JobApplicationListrMock</div>)
render(<MemoryRouter>
<App />
</MemoryRouter>);
expect(screen.getByText("PrimarySearchAppBarMock")).toBeInTheDocument();
expect(screen.getByText("AppHeaderMock")).toBeInTheDocument();
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,20 @@ import IconButton from '@mui/material/IconButton';
import Badge from '@mui/material/Badge';
import EmojiEventsIcon from '@mui/icons-material/EmojiEvents';
import AddCircleIcon from '@mui/icons-material/AddCircle';
import MailIcon from '@mui/icons-material/Mail';
import NotificationsIcon from '@mui/icons-material/Notifications';
import EventAvailableIcon from '@mui/icons-material/EventAvailable';
import AccountCircle from '@mui/icons-material/AccountCircle';
import MoreIcon from '@mui/icons-material/MoreVert';
import { useQuery } from '@apollo/client';
import { GET_PROFILE } from '../graphql/query';
import { GET_PROFILE, GET_ALL_OFFERS, GET_ALL_INTERVIEWS } from '../graphql/query';
import SearchBar from './SearchBar';
import JobApplicationDialog from './JobApplicationDialog';
import ProfileDialog from './ProfileDialog';
import JobApplicationList from './JobApplicationList';
import MobileMenu from './MobileMenu';
import dayjs from 'dayjs';

export default function PrimarySearchAppBar() {
export default function AppHeader() {
const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = useState(null);
const [jobApplicationOpen, setJobApplicationOpen] = useState(false);
const [profileOpen, setProfileOpen] = useState(false);
Expand All @@ -33,6 +34,31 @@ export default function PrimarySearchAppBar() {
variables: { id },
});

const { data: offersData, loading: offersLoading, error: offersError } = useQuery(GET_ALL_OFFERS, {
fetchPolicy: 'network-only',
});

const { data: interviewsData, loading: interviewsLoading, error: interviewsError } = useQuery(GET_ALL_INTERVIEWS, {
fetchPolicy: 'network-only',
});

const offerCount = offersData?.allOffer?.length || 0;

const filteredInterviews = interviewsData?.allInterview?.filter((interview) => {
const interviewDate = dayjs(interview.interviewDate);
if (!interviewDate.isValid()) {
console.warn('Invalid dayjs object for interviewDate:', interview.interviewDate);
return false;
}

return (
(interviewDate.isSame(dayjs(), 'day') || interviewDate.isAfter(dayjs(), 'day')) &&
['open', 'pending'].includes(interview.status)
);
}) || [];

const interviewCount = filteredInterviews?.length || 0;

const handleProfileMenuOpen = () => {
setProfileOpen(true);
setProfile(data.profileById);
Expand Down Expand Up @@ -88,13 +114,13 @@ export default function PrimarySearchAppBar() {
<IconButton size="large" aria-label="New" color="inherit" onClick={handleJobApplicationOpen}>
<AddCircleIcon />
</IconButton>
<IconButton size="large" aria-label="show 4 new mails" color="inherit">
<Badge badgeContent={4} color="error">
<MailIcon />
<IconButton size="large" color="inherit">
<Badge badgeContent={interviewsLoading ? '...' : interviewCount} color="error">
<EventAvailableIcon />
</Badge>
</IconButton>
<IconButton size="large" aria-label="show 17 new notifications" color="inherit">
<Badge badgeContent={17} color="error">
<IconButton size="large" color="inherit">
<Badge badgeContent={offersLoading ? '...' : offerCount} color="error">
<NotificationsIcon />
</Badge>
</IconButton>
Expand Down Expand Up @@ -129,6 +155,8 @@ export default function PrimarySearchAppBar() {
handleMobileMenuClose={handleMobileMenuClose}
handleProfileMenuOpen={handleProfileMenuOpen}
handleJobApplicationOpen={handleJobApplicationOpen}
interviewCount={interviewCount}
offerCount={offerCount}
/>
</AppBar>
<JobApplicationList searchTerm={searchTerm} />
Expand Down
18 changes: 9 additions & 9 deletions src/components/MobileMenu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import Badge from '@mui/material/Badge';
import AddCircleIcon from '@mui/icons-material/AddCircle';
import MailIcon from '@mui/icons-material/Mail';
import EventAvailableIcon from '@mui/icons-material/EventAvailable';
import NotificationsIcon from '@mui/icons-material/Notifications';
import AccountCircle from '@mui/icons-material/AccountCircle';

export default function MobileMenu({ mobileMoreAnchorEl, isMobileMenuOpen, handleMobileMenuClose, handleProfileMenuOpen, handleJobApplicationOpen }) {
export default function MobileMenu({ mobileMoreAnchorEl, isMobileMenuOpen, handleMobileMenuClose, handleProfileMenuOpen, handleJobApplicationOpen, interviewCount, offerCount }) {
const mobileMenuId = 'primary-search-account-menu-mobile';
return (
<Menu
Expand All @@ -33,20 +33,20 @@ export default function MobileMenu({ mobileMoreAnchorEl, isMobileMenuOpen, handl
<p>New</p>
</MenuItem>
<MenuItem>
<IconButton size="large" aria-label="show 4 new mails" color="inherit">
<Badge badgeContent={4} color="error">
<MailIcon />
<IconButton size="large" color="inherit">
<Badge badgeContent={interviewCount} color="error">
<EventAvailableIcon />
</Badge>
</IconButton>
<p>Offers</p>
<p>Interviews</p>
</MenuItem>
<MenuItem>
<IconButton size="large" aria-label="show 17 new notifications" color="inherit">
<Badge badgeContent={17} color="error">
<IconButton size="large" color="inherit">
<Badge badgeContent={offerCount} color="error">
<NotificationsIcon />
</Badge>
</IconButton>
<p>Interviews</p>
<p>Offers</p>
</MenuItem>
<MenuItem onClick={handleProfileMenuOpen}>
<IconButton size="large" aria-label="account of current user" aria-controls="primary-search-account-menu" aria-haspopup="true" color="inherit">
Expand Down
17 changes: 13 additions & 4 deletions src/components/forms/InterviewsForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import ConfirmDialog from '../common/ConfirmDialog';
import SnackbarComponent from '../common/SnackbarComponent';
import useSnackbar from '../hooks/useSnackbar';
import { ADD_INTERVIEW, UPDATE_INTERVIEW, DELETE_INTERVIEW } from '../../graphql/mutation';
import { GET_INTERVIEWS_BY_JOB_APPLICATION_ID } from '../../graphql/query';
import { GET_INTERVIEWS_BY_JOB_APPLICATION_ID, GET_ALL_INTERVIEWS } from '../../graphql/query';
import dayjs from 'dayjs';
import { Grid } from '@mui/material';

Expand All @@ -30,15 +30,24 @@ export default function InterviewsForm({ jobApplicationId }) {
});

const [addInterview] = useMutation(ADD_INTERVIEW, {
refetchQueries: [{ query: GET_INTERVIEWS_BY_JOB_APPLICATION_ID, variables: { jobApplicationId } }],
refetchQueries: [
{ query: GET_INTERVIEWS_BY_JOB_APPLICATION_ID, variables: { jobApplicationId } },
{ query: GET_ALL_INTERVIEWS }
],
});

const [updateInterview] = useMutation(UPDATE_INTERVIEW, {
refetchQueries: [{ query: GET_INTERVIEWS_BY_JOB_APPLICATION_ID, variables: { jobApplicationId } }],
refetchQueries: [
{ query: GET_INTERVIEWS_BY_JOB_APPLICATION_ID, variables: { jobApplicationId } },
{ query: GET_ALL_INTERVIEWS }
],
});

const [deleteInterview] = useMutation(DELETE_INTERVIEW, {
refetchQueries: [{ query: GET_INTERVIEWS_BY_JOB_APPLICATION_ID, variables: { jobApplicationId } }],
refetchQueries: [
{ query: GET_INTERVIEWS_BY_JOB_APPLICATION_ID, variables: { jobApplicationId } },
{ query: GET_ALL_INTERVIEWS }
],
onError: (err) => {
console.error('Error deleting interview:', err.message);
showSnackbar('Error deleting interview', 'error');
Expand Down
8 changes: 6 additions & 2 deletions src/components/forms/OfferForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { DesktopDatePicker } from '@mui/x-date-pickers/DesktopDatePicker';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { ADD_OFFER, UPDATE_OFFER, DELETE_OFFER } from '../../graphql/mutation';
import { GET_OFFER } from '../../graphql/query';
import { GET_OFFER, GET_ALL_OFFERS } from '../../graphql/query';
import dayjs from 'dayjs';
import { Grid } from '@mui/material';

Expand Down Expand Up @@ -43,7 +43,10 @@ export default function OfferForm({ jobApplicationId, handleClose }) {
});

const [deleteOffer, { loading: deleteOfferLoading }] = useMutation(DELETE_OFFER, {
refetchQueries: [{ query: GET_OFFER, variables: { jobApplicationId } }],
refetchQueries: [
{ query: GET_OFFER, variables: { jobApplicationId } },
{ query: GET_ALL_OFFERS },
],
});

useEffect(() => {
Expand Down Expand Up @@ -100,6 +103,7 @@ export default function OfferForm({ jobApplicationId, handleClose }) {
description: offerData.description,
offerDate: offerData.offerDate,
},
refetchQueries: [{ query: GET_ALL_OFFERS }],
});
showSnackbar('Offer added successfully!', 'success');
}
Expand Down
13 changes: 13 additions & 0 deletions src/graphql/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,19 @@ export const GET_OFFER = gql`
`
;

export const GET_ALL_OFFERS = gql`
query GetOffers {
allOffer {
id
jobApplicationId
offerDate
salaryOffered
description
}
}
`
;

export const GET_ALL_INTERVIEWS = gql`
query GetAllInterviews {
allInterview {
Expand Down

0 comments on commit bd05c57

Please sign in to comment.