Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Birthday reminders for Persons on your list #339

Merged
merged 11 commits into from
Mar 31, 2022
Merged
1 change: 1 addition & 0 deletions forgettable-frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ yarn-error.log*

# Firebase Config
/src/firebase-config.js
forgettable_service_account.json

# dotenv environment variable files
.env
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from 'react';
import {Avatar} from '@mui/material';
import classes from './UpcomingBirthdaySummary.module.css';
import {getBirthdayDate} from '../../functions/dateFormatter';
import UnknownDetail from '../UnknownDetail/UnknownDetail';
import PropTypes from 'prop-types';
import {getImageSrcFromBuffer} from '../../functions/getImageSrcFromBuffer';

/*
* Component for displaying information for upcoming birthdays.
* Based off of EncounterCardSummary and PersonCardSummary components
* orginally authored by Mercury Lin (lin8231)
*
* Author: Aaron Song (ason720)
*/
const UpcomingBirthdaySummary = (props) => {
return (
<div
className={classes.UpcomingBirthdaySummary}
onClick={props.onClick}
data-testid="container-card"
>
<div className={classes.ContentContainer}>
<div className={classes.HeaderContainer}>
<Avatar
alt={props.firstName}
src={getImageSrcFromBuffer(props.img)}
sx={{
height: '70px',
width: '70px',
marginRight: '14px',
backgroundColor:
getComputedStyle(document.body).getPropertyValue('--prmry'),
fontSize:
getComputedStyle(document.body)
.getPropertyValue('--text-xxlarge'),
}}
/>
<div className={classes.IdentityInfoConatiner}>
<h3 data-testid="name-element">{props.firstName}</h3>
</div>
</div>
<div className={classes.DetailsContainer}>
<p>
{'Birthday: '}
{props.birthday ?
<span data-testid="birthdate-element">
{getBirthdayDate(props.birthday)}
</span> :
<UnknownDetail />}
</p>
</div>
</div>
</div>
);
};

UpcomingBirthdaySummary.propTypes = {
id: PropTypes.string,
firstName: PropTypes.string.isRequired,
img: PropTypes.string,
birthday: PropTypes.instanceOf(Date),
onClick: PropTypes.func.isRequired,
};

export default UpcomingBirthdaySummary;
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
@import '../../colours.css';

.UpcomingBirthdaySummary{
height: 150px;
width:240px;
cursor: pointer;
border-radius: var(--radius-card);
background-color: var(--card);
transition: 0.3s;
display: flex;
padding: 20px 22px;
box-sizing: border-box;
}

.UpcomingBirthdaySummary:hover {
background-color: var(--hilit);
}

.ContentContainer {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}

.HeaderContainer {
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}

.IdentityInfoConatiner {
flex: 1;
display: flex;
flex-direction: column;

}

.IdentityInfoConatiner > h3 {
font-size: var(--text-medium);
color: var(--txt1);
font-weight: var(--font-semibold);
margin: 0;
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1; /* number of lines to show */
line-clamp: 1;
-webkit-box-orient: vertical;
}

.IdentityInfoConatiner > p {
font-size: var(--text-card-body-normal);
margin: 0;
color: var(--txt2);
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2; /* number of lines to show */
line-clamp: 2;
-webkit-box-orient: vertical;
}

.DetailsContainer {
flex: 1;
display: flex;
flex-direction: column;
}

.DetailsContainer > p {
color: var(--txt2);
font-size: var(--text-xsmall);
}

.DescriptionText {
margin-top: -2px;
overflow: hidden;
text-align: left;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3; /* number of lines to show */
line-clamp: 3;
-webkit-box-orient: vertical;
}

.IdentityInfoConatiner > h3 {
text-align: left;
text-overflow: ellipsis;
overflow: hidden;
max-width: 110px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import {render, fireEvent, cleanup} from '@testing-library/react';

import ShallowRenderer from 'react-test-renderer/shallow';

import UpcomingBirthdaySummary from '../UpcomingBirthdaySummary';
import moment from 'moment';

jest.mock('../../../services');

const mockedUsedNavigate = jest.fn();

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: () => mockedUsedNavigate,
}));

it('renders UpcomingBirthdaySummary UI with correct hierarchy', () => {
const renderer = new ShallowRenderer();
renderer.render(<UpcomingBirthdaySummary
firstName='Bob'
onClick={() => { }} />);
const result = renderer.getRenderOutput();
expect(result).toMatchSnapshot();
});

afterEach(cleanup);

it('successfully fires event when card is clicked', () => {
const handleClick = jest.fn();

const {getByTestId} = render(
<UpcomingBirthdaySummary
firstName='Bob'
birthday={moment(1648698811606).toDate()}
onClick={handleClick}
/>);

const node = getByTestId('container-card');

fireEvent.click(node);
expect(handleClick).toHaveBeenCalledTimes(1);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders UpcomingBirthdaySummary UI with correct hierarchy 1`] = `
<div
className="UpcomingBirthdaySummary"
data-testid="container-card"
onClick={[Function]}
>
<div
className="ContentContainer"
>
<div
className="HeaderContainer"
>
<ForwardRef(Avatar)
alt="Bob"
src={null}
sx={
Object {
"backgroundColor": "",
"fontSize": "",
"height": "70px",
"marginRight": "14px",
"width": "70px",
}
}
/>
<div
className="IdentityInfoConatiner"
>
<h3
data-testid="name-element"
>
Bob
</h3>
</div>
</div>
<div
className="DetailsContainer"
>
<p>
Birthday:
<UnknownDetail />
</p>
</div>
</div>
</div>
`;
40 changes: 40 additions & 0 deletions forgettable-frontend/src/functions/__tests__/dateFormatter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
getLongDateStringWithSpaces,
calculateAge,
getLongDateStringWithSlashes,
getMonthAndDay,
getDayOfWeek,
} from '../dateFormatter';

test(
Expand Down Expand Up @@ -83,3 +85,41 @@ test('getLongDateStringWithSlashes: should return a string representing "Unknown
expect(formattedString).toBe('Unknown');
};
});

test('getDayOfWeek: should return a string representing "Unknown" given a null Date object',
() => {
() => {
const formattedString = getDayOfWeek(null);

expect(formattedString).toBe('Unknown');
};
});

test('getDayOfWeek: should format date into day of the week',
() => {
() => {
const date = new Date('30-03-2022');
const formattedString = getDayOfWeek(date);

expect(formattedString).toBe('Wednesday');
};
});

test('getMonthAndDay: should return a string representing "Unknown" given a null Date object',
() => {
() => {
const formattedString = getMonthAndDay(null);

expect(formattedString).toBe('Unknown');
};
});

test('getMonthAndDay: should format date into day of the week',
() => {
() => {
const date = new Date('30-03-2022');
const formattedString = getMonthAndDay(date);

expect(formattedString).toBe('30 March');
};
});
Loading