Skip to content

Commit

Permalink
feat(trackerCard): add TrackerCard and use it on TrackerList
Browse files Browse the repository at this point in the history
  • Loading branch information
Clm-Roig committed Mar 16, 2022
1 parent b1264ae commit 50de224
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 32 deletions.
1 change: 0 additions & 1 deletion src/app/AppBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ const AppBar: FC<Props> = ({ toggleDrawerMenu }) => {
edge="start"
color="inherit"
aria-label="menu"
sx={{ mr: 2 }}
onClick={toggleDrawerMenu}>
<MenuIcon />
</IconButton>
Expand Down
28 changes: 28 additions & 0 deletions src/components/TrackerCard/TrackerCard.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { render, screen } from '@testing-library/react';
import { subDays } from 'date-fns';
import TrackerStatus from '../../models/TrackerStatus';
import formatDate from '../../utils/formatDate';
import TrackerCard from './TrackerCard';

const tracker1 = {
beginDate: subDays(new Date(), 3).toString(),
defaultQuantity: 15,
duration: 13,
name: 'Faire des pompes',
remainingDays: 10,
status: TrackerStatus.active,
unit: 'pompes',
entries: []
};
const setup = () => render(<TrackerCard tracker={tracker1} />);

describe('<TrackerCard />', () => {
it('shows tracker informations', () => {
setup();
const { beginDate, name, defaultQuantity, remainingDays, unit } = tracker1;
expect(screen.getByText(name)).toBeInTheDocument();
expect(screen.getByText('Reste ' + remainingDays + ' jours')).toBeInTheDocument();
expect(screen.getByText('Commencé le ' + formatDate(new Date(beginDate)))).toBeInTheDocument();
expect(screen.getByText(defaultQuantity + ' ' + unit)).toBeInTheDocument();
});
});
49 changes: 44 additions & 5 deletions src/components/TrackerCard/TrackerCard.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,53 @@
import { Card, Typography } from '@mui/material';
import { FC } from 'react';

import SliceStatus from '../../models/SliceStatus';
import {
Box,
Card,
CardProps,
CardActions,
CardContent,
CardHeader,
IconButton,
Chip
} from '@mui/material';
import formatDate from '../../utils/formatDate';
import Tracker from '../../models/Tracker';
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
import CheckIcon from '@mui/icons-material/Check';
import TimerIcon from '@mui/icons-material/Timer';
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';

interface Props {
tracker: Tracker;
cardProps?: CardProps;
}
const TrackerCard: FC<Props> = ({ tracker }) => {
return <Card></Card>;
const TrackerCard: FC<Props> = ({ tracker, cardProps }) => {
const { beginDate, defaultQuantity, name, remainingDays, unit } = tracker;
return (
<Card {...cardProps}>
<CardHeader title={name} subheader={`Commencé le ${formatDate(new Date(beginDate))}`} />
{(defaultQuantity || remainingDays) && (
<CardContent>
{defaultQuantity && <Chip label={`${defaultQuantity} ${unit}`} />}
{remainingDays && (
<Chip color="secondary" label={`Reste ${remainingDays} jours`} icon={<TimerIcon />} />
)}
</CardContent>
)}
<CardActions>
<Box sx={{ display: 'flex', justifyContent: 'space-between', width: '100%' }}>
<IconButton color="success" size="large">
<CheckIcon fontSize="large" />
</IconButton>
<IconButton color="success" size="large">
<CheckCircleIcon fontSize="large" />
</IconButton>
<IconButton size="large">
<VisibilityOffIcon fontSize="large" />
</IconButton>
</Box>
</CardActions>
</Card>
);
};

export default TrackerCard;
14 changes: 6 additions & 8 deletions src/components/trackerList/TrackerList.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Box, CircularProgress, List, ListItem, Typography } from '@mui/material';
import { Box, CircularProgress, Typography } from '@mui/material';
import { useEffect } from 'react';

import { useAppSelector, useAppDispatch } from '../../app/hooks';
import SliceStatus from '../../models/SliceStatus';
import { fetchAllTrackers } from '../../store/trackers/trackersSlice';
import selectTrackers from '../../store/trackers/trackers.selectors';

import TrackerCard from '../TrackerCard/TrackerCard';

function TrackerList() {
const { status, trackers } = useAppSelector(selectTrackers);
const dispatch = useAppDispatch();
Expand All @@ -21,15 +23,11 @@ function TrackerList() {
{status === SliceStatus.loading && <CircularProgress />}
{trackers && trackers.length === 0 && <Typography>There are no trackers.</Typography>}
{trackers && trackers.length > 0 && (
<List>
<>
{trackers.map((t) => (
<ListItem key={t.name}>
<Typography variant="body1">
{t.name} - {new Date(t.beginDate).toLocaleDateString()} - {t.status}
</Typography>
</ListItem>
<TrackerCard tracker={t} key={t.name} cardProps={{ sx: { m: 1 } }} />
))}
</List>
</>
)}
</Box>
);
Expand Down
18 changes: 16 additions & 2 deletions src/store/trackers/trackers.actions.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { subDays } from 'date-fns';
import Tracker from '../../models/Tracker';
import TrackerStatus from '../../models/TrackerStatus';

Expand All @@ -11,14 +12,27 @@ class TrackersActions {
data: [
{
beginDate: new Date().toString(),
name: 'Boire',
name: "Boire plus d'eau",
defaultQuantity: 1,
status: TrackerStatus.active,
unit: "litre d'eau",
entries: []
},
{
beginDate: new Date().toString(),
name: 'Manger',
defaultQuantity: 1,
name: 'Faire du yoga',
status: TrackerStatus.active,
unit: 'séance',
entries: []
},
{
beginDate: subDays(new Date(), 7).toString(),
defaultQuantity: 15,
duration: 45,
name: 'Faire des pompes',
status: TrackerStatus.active,
unit: 'pompes',
entries: []
}
]
Expand Down
38 changes: 23 additions & 15 deletions src/store/trackers/trackers.selectors.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
import { RootState } from '../store';
import Tracker from '../../models/Tracker';
import { intervalToDuration } from 'date-fns';
import { formatDuration, intervalToDuration } from 'date-fns';

const selectTrackers = (state: RootState) => {
const prevTrackers = state.trackers.trackers;
const newTrackers = prevTrackers?.map((t) => {
let trackerObj = t as Tracker;
const { beginDate, duration } = trackerObj;
if (beginDate && duration) {
const beginDateObj = new Date(beginDate);
const estimatedEndDateObj = new Date(beginDate);
estimatedEndDateObj.setDate(estimatedEndDateObj.getDate() + duration);

const remainingDuration = intervalToDuration({
start: beginDateObj,
end: estimatedEndDateObj
});

trackerObj = {
...trackerObj,
remainingDays: Number(formatDuration(remainingDuration, { format: ['days'] }).split(' ')[0])
};
}
return trackerObj;
});
return {
...state.trackers,
trackers: state.trackers.trackers?.map((t) => {
const trackerObj = t as Tracker;
const { beginDate, duration } = trackerObj;
if (beginDate && duration) {
const beginDateObj = new Date(beginDate);
const estimatedEndDateObj = new Date(beginDate);
estimatedEndDateObj.setDate(estimatedEndDateObj.getDate() + duration);
trackerObj.remainingDays = intervalToDuration({
start: beginDateObj,
end: estimatedEndDateObj
}).days;
}
return trackerObj;
})
trackers: newTrackers ? [...newTrackers] : prevTrackers
};
};

Expand Down
2 changes: 1 addition & 1 deletion src/store/trackers/trackersSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const fetchAllTrackers = createAsyncThunk('trackers/fetchAllTrackers', as
// ===== Reducers

export const trackersSlice = createSlice({
name: 'counter',
name: 'trackers',
initialState,
reducers: {},
// The `extraReducers` field lets the slice handle actions defined elsewhere,
Expand Down

0 comments on commit 50de224

Please sign in to comment.