From c4d7ca1685757a8aefcaff839f1d3e4f29039158 Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 11 Apr 2022 11:44:28 +0200 Subject: [PATCH] feat(hideTracker): add hide / make visible tracker feature --- .../TrackerCard/TrackerCardActions.tsx | 37 +++-- .../MakeHiddenDialog.tsx | 8 +- .../MakeVisibleDialog.tsx | 8 +- src/store/trackers/trackers.selectors.spec.ts | 3 +- src/store/trackers/trackers.selectors.ts | 4 +- src/store/trackers/trackersSlice.spec.ts | 139 +++++++++++------- src/store/trackers/trackersSlice.ts | 22 ++- 7 files changed, 144 insertions(+), 77 deletions(-) diff --git a/src/components/TrackerCard/TrackerCardActions.tsx b/src/components/TrackerCard/TrackerCardActions.tsx index b73a8968..ea58b11c 100644 --- a/src/components/TrackerCard/TrackerCardActions.tsx +++ b/src/components/TrackerCard/TrackerCardActions.tsx @@ -10,7 +10,12 @@ import { FC, useState } from 'react'; import { useAppDispatch } from '../../app/hooks'; import Completion from '../../models/Completion'; import Tracker from '../../models/Tracker'; -import { completelyValidate, customValidate } from '../../store/trackers/trackersSlice'; +import { + completelyValidate, + customValidate, + hideTracker, + makeTrackerVisible +} from '../../store/trackers/trackersSlice'; import CompleteValidationDialog from '../TrackerValidationDialog/CompleteValidationDialog'; import CustomValidationDialog from '../TrackerValidationDialog/CustomValidationDialog'; import MakeHiddenDialog from '../TrackerValidationDialog/MakeHiddenDialog'; @@ -30,11 +35,11 @@ const TrackerCardActions: FC = ({ tracker }) => { const dispatch = useAppDispatch(); - const [isCompleteValidationOpen, setIsCompleteValidationOpen] = useState(false); const { enqueueSnackbar } = useSnackbar(); + const [isCompleteValidationOpen, setIsCompleteValidationOpen] = useState(false); const [isCustomValidationOpen, setIsCustomValidationOpen] = useState(false); - const [isMakeVisible, setIsMakeVisible] = useState(false); - const [isMakeHidden, setIsMakeHidden] = useState(false); + const [isMakeVisibleOpen, setIsMakeVisibleOpen] = useState(false); + const [isMakeHiddenOpen, setIsMakeHiddenOpen] = useState(false); const handleCompleteValidation = () => { dispatch(completelyValidate(tracker.id)); @@ -51,15 +56,15 @@ const TrackerCardActions: FC = ({ // TODO: remove next line when feature is implemented // eslint-disable-next-line @typescript-eslint/no-unused-vars const handleMakeVisible = () => { - // eslint-disable-next-line no-console - console.log('make visible to be implementend'); + dispatch(makeTrackerVisible(tracker.id)); + setIsMakeVisibleOpen(false); + enqueueSnackbar('Tracker affiché !', { variant: 'success' }); }; - // TODO: remove next line when feature is implemented - // eslint-disable-next-line @typescript-eslint/no-unused-vars const handleMakeHidden = () => { - // eslint-disable-next-line no-console - console.log('make hidden to be implementend'); + dispatch(hideTracker(tracker.id)); + setIsMakeHiddenOpen(false); + enqueueSnackbar('Tracker masqué !', { variant: 'success' }); }; const isHidden = tracker.dateHidden && isToday(new Date(tracker.dateHidden)); @@ -89,11 +94,11 @@ const TrackerCardActions: FC = ({ )} {isHidden ? ( - setIsMakeVisible(true)}> + setIsMakeVisibleOpen(true)}> ) : ( - setIsMakeHidden(true)}> + setIsMakeHiddenOpen(true)}> )} @@ -125,8 +130,8 @@ const TrackerCardActions: FC = ({ /> setIsMakeVisible(false), + open: isMakeVisibleOpen, + onClose: () => setIsMakeVisibleOpen(false), sx: { '.MuiDialog-paper': { bgcolor: 'secondary' } } @@ -136,8 +141,8 @@ const TrackerCardActions: FC = ({ /> setIsMakeHidden(false), + open: isMakeHiddenOpen, + onClose: () => setIsMakeHiddenOpen(false), sx: { '.MuiDialog-paper': { bgcolor: 'secondary' } } diff --git a/src/components/TrackerValidationDialog/MakeHiddenDialog.tsx b/src/components/TrackerValidationDialog/MakeHiddenDialog.tsx index 0c32c4d6..b0f10246 100644 --- a/src/components/TrackerValidationDialog/MakeHiddenDialog.tsx +++ b/src/components/TrackerValidationDialog/MakeHiddenDialog.tsx @@ -21,7 +21,7 @@ interface Props { } const MakeHiddenDialog: FC = ({ dialogProps, onValidation, tracker }) => { - const { name, requiredCompletions } = tracker; + const { name } = tracker; return ( @@ -29,10 +29,12 @@ const MakeHiddenDialog: FC = ({ dialogProps, onValidation, tracker }) => {name} - [Masquer tracker] En cours de développement... + Voulez-vous masquer ce tracker ? - + ); diff --git a/src/components/TrackerValidationDialog/MakeVisibleDialog.tsx b/src/components/TrackerValidationDialog/MakeVisibleDialog.tsx index 8c0984ce..951b168e 100644 --- a/src/components/TrackerValidationDialog/MakeVisibleDialog.tsx +++ b/src/components/TrackerValidationDialog/MakeVisibleDialog.tsx @@ -21,7 +21,7 @@ interface Props { } const MakeVisibleValidationDialog: FC = ({ dialogProps, onValidation, tracker }) => { - const { name, requiredCompletions } = tracker; + const { name } = tracker; return ( @@ -29,10 +29,12 @@ const MakeVisibleValidationDialog: FC = ({ dialogProps, onValidation, tra {name} - [Rendre visible] En cours de développement... + Voulez-vous afficher ce tracker ? - + ); diff --git a/src/store/trackers/trackers.selectors.spec.ts b/src/store/trackers/trackers.selectors.spec.ts index f4586fdf..92ff90c1 100644 --- a/src/store/trackers/trackers.selectors.spec.ts +++ b/src/store/trackers/trackers.selectors.spec.ts @@ -62,7 +62,8 @@ describe('selectHiddenTrackers()', () => { trackers: [ { ...testTracker1, dateHidden: new Date().toString() }, testTracker2, - { ...testTracker3, dateHidden: new Date().toString() } + { ...testTracker3, dateHidden: new Date().toString() }, + { ...testTracker3, dateHidden: subDays(new Date(), 2).toString() } // Should not be selected because it was hidden in the pas ] } }; diff --git a/src/store/trackers/trackers.selectors.ts b/src/store/trackers/trackers.selectors.ts index 2bd33079..49ad64b5 100644 --- a/src/store/trackers/trackers.selectors.ts +++ b/src/store/trackers/trackers.selectors.ts @@ -21,8 +21,8 @@ const selectHiddenTrackers = (state: RootState) => { }; const selectTrackersDone = (state: RootState) => { - const newTrackers = formatTrackers(state.trackers.trackers).filter( - (t) => t.status === TrackerStatus.done + const newTrackers = removeHiddenTrackers( + formatTrackers(state.trackers.trackers).filter((t) => t.status === TrackerStatus.done) ); return { diff --git a/src/store/trackers/trackersSlice.spec.ts b/src/store/trackers/trackersSlice.spec.ts index 2ccb4c9c..1929cd44 100644 --- a/src/store/trackers/trackersSlice.spec.ts +++ b/src/store/trackers/trackersSlice.spec.ts @@ -4,7 +4,9 @@ import trackersReducer, { completelyValidate, createTracker, customValidate, - deleteTracker + deleteTracker, + hideTracker, + makeTrackerVisible } from './trackersSlice'; describe('trackers reducer', () => { @@ -15,58 +17,95 @@ describe('trackers reducer', () => { trackers: [] }); }); - it('should handle a tracker complete validation', () => { - const finalState = trackersReducer( - { error: {}, status: SliceStatus.idle, trackers: [testTracker1] }, - completelyValidate(testTracker1Id) - ); - const res = finalState.trackers[0]; - expect(res).toBeDefined(); - const entries = res?.entries; - expect(entries?.length).toEqual(1); - const entry = entries?.[0]; - expect(entry?.completions).toEqual(testTracker1.requiredCompletions); - expect(entry?.trackerId).toEqual(testTracker1.id); - }); - it('should handle a tracker custom validation', () => { - const partialCompletions = [ - { - quantity: 5, - unit: 'push-ups' - }, - { - quantity: 20, - unit: 'squats' - } - ]; - const finalState = trackersReducer( - { error: {}, status: SliceStatus.idle, trackers: [testTracker1] }, - customValidate({ id: testTracker1Id, completions: partialCompletions }) - ); + describe('Tracker validation', () => { + it('should handle a tracker complete validation', () => { + const finalState = trackersReducer( + { error: {}, status: SliceStatus.idle, trackers: [testTracker1] }, + completelyValidate(testTracker1Id) + ); + + const res = finalState.trackers[0]; + expect(res).toBeDefined(); + const entries = res?.entries; + expect(entries?.length).toEqual(1); + const entry = entries?.[0]; + expect(entry?.completions).toEqual(testTracker1.requiredCompletions); + expect(entry?.trackerId).toEqual(testTracker1.id); + }); - const res = finalState.trackers[0]; - expect(res).toBeDefined(); - const entries = res?.entries; - expect(entries?.length).toEqual(1); - const entry = entries?.[0]; - expect(entry?.completions).toEqual(partialCompletions); - expect(entry?.trackerId).toEqual(testTracker1.id); + it('should handle a tracker custom validation', () => { + const partialCompletions = [ + { + quantity: 5, + unit: 'push-ups' + }, + { + quantity: 20, + unit: 'squats' + } + ]; + const finalState = trackersReducer( + { error: {}, status: SliceStatus.idle, trackers: [testTracker1] }, + customValidate({ id: testTracker1Id, completions: partialCompletions }) + ); + + const res = finalState.trackers[0]; + expect(res).toBeDefined(); + const entries = res?.entries; + expect(entries?.length).toEqual(1); + const entry = entries?.[0]; + expect(entry?.completions).toEqual(partialCompletions); + expect(entry?.trackerId).toEqual(testTracker1.id); + }); }); - it('should handle a tracker deletion', () => { - const finalState = trackersReducer( - { error: {}, status: SliceStatus.idle, trackers: [testTracker1] }, - deleteTracker(testTracker1Id) - ); - expect(finalState.trackers.length).toEqual(0); + describe('Tracker deletion', () => { + it('should handle a tracker deletion', () => { + const finalState = trackersReducer( + { error: {}, status: SliceStatus.idle, trackers: [testTracker1] }, + deleteTracker(testTracker1Id) + ); + expect(finalState.trackers.length).toEqual(0); + }); }); - it('should handle a tracker creation', () => { - const finalState = trackersReducer( - { error: {}, status: SliceStatus.idle, trackers: [testTracker1] }, - createTracker(testTracker2) - ); - expect(finalState.trackers.length).toEqual(2); - expect(finalState.trackers.find((t) => t.id === testTracker1Id)).toEqual(testTracker1); - expect(finalState.trackers.find((t) => t.id === testTracker2Id)).toEqual(testTracker2); + describe('Tracker creation', () => { + it('should handle a tracker creation', () => { + const finalState = trackersReducer( + { error: {}, status: SliceStatus.idle, trackers: [testTracker1] }, + createTracker(testTracker2) + ); + expect(finalState.trackers.length).toEqual(2); + expect(finalState.trackers.find((t) => t.id === testTracker1Id)).toEqual(testTracker1); + expect(finalState.trackers.find((t) => t.id === testTracker2Id)).toEqual(testTracker2); + }); + }); + describe('Hide tracker', () => { + it('should hide a tracker', () => { + const finalState = trackersReducer( + { error: {}, status: SliceStatus.idle, trackers: [testTracker1, testTracker2] }, + hideTracker(testTracker1.id) + ); + expect( + finalState.trackers.find((t) => t.id === testTracker1Id)?.dateHidden + ).not.toBeUndefined(); + expect(finalState.trackers.find((t) => t.id === testTracker2Id)?.dateHidden).toBeUndefined(); + }); + }); + describe('Make a tracker visible', () => { + it('should make a tracker visible', () => { + const finalState = trackersReducer( + { + error: {}, + status: SliceStatus.idle, + trackers: [ + { ...testTracker1, dateHidden: new Date().toString() }, + { ...testTracker2, dateHidden: new Date().toString() } + ] + }, + makeTrackerVisible(testTracker1.id) + ); + expect(finalState.trackers.find((t) => t.id === testTracker1Id)?.dateHidden).toBeUndefined(); + expect(finalState.trackers.find((t) => t.id == testTracker2Id)?.dateHidden).toBeDefined(); + }); }); }); diff --git a/src/store/trackers/trackersSlice.ts b/src/store/trackers/trackersSlice.ts index 31604070..14d524b0 100644 --- a/src/store/trackers/trackersSlice.ts +++ b/src/store/trackers/trackersSlice.ts @@ -69,6 +69,18 @@ export const trackersSlice = createSlice({ ...state, trackers: filteredTrackers }; + }, + hideTracker: (state, action: PayloadAction) => { + const idx = state.trackers.findIndex((t) => t.id === action.payload); + if (idx !== -1) { + state.trackers[idx].dateHidden = new Date().toString(); + } + }, + makeTrackerVisible: (state, action: PayloadAction) => { + const idx = state.trackers.findIndex((t) => t.id === action.payload); + if (idx !== -1) { + state.trackers[idx].dateHidden = undefined; + } } } // The `extraReducers` field lets the slice handle actions defined elsewhere, @@ -76,6 +88,12 @@ export const trackersSlice = createSlice({ // extraReducers: (builder) => {}) }); -export const { createTracker, completelyValidate, customValidate, deleteTracker } = - trackersSlice.actions; +export const { + createTracker, + completelyValidate, + customValidate, + deleteTracker, + hideTracker, + makeTrackerVisible +} = trackersSlice.actions; export default trackersSlice.reducer;