diff --git a/src/ui/pages/CredentialDetails/CredentialDetails.scss b/src/ui/pages/CredentialDetails/CredentialDetails.scss index 271982965..4a9812690 100644 --- a/src/ui/pages/CredentialDetails/CredentialDetails.scss +++ b/src/ui/pages/CredentialDetails/CredentialDetails.scss @@ -8,6 +8,17 @@ .page-header { margin-top: 0.625rem; } + + .notification-selected { + width: fit-content; + --checkbox-background-checked: var(--ion-color-primary-gradient); + --checkmark-color: var(--ion-color-primary); + --border-width: 0.115rem; + + &.checkbox-checked { + --border-width: 0; + } + } } .cred-detail-spinner-container { diff --git a/src/ui/pages/CredentialDetails/CredentialDetails.test.tsx b/src/ui/pages/CredentialDetails/CredentialDetails.test.tsx index c0b2d965a..234c9d89c 100644 --- a/src/ui/pages/CredentialDetails/CredentialDetails.test.tsx +++ b/src/ui/pages/CredentialDetails/CredentialDetails.test.tsx @@ -11,6 +11,7 @@ import { removeFavouritesCredsCache, setCredsCache, } from "../../../store/reducers/credsCache"; +import { setNotificationDetailCache } from "../../../store/reducers/notificationsCache"; import { setCurrentRoute, setToastMsg, @@ -78,6 +79,9 @@ const initialStateNoPasswordCurrent = { biometricsCache: { enabled: false, }, + notificationsCache: { + notificationDetailCache: null, + }, }; const initialStateNoPasswordArchived = { @@ -101,6 +105,9 @@ const initialStateNoPasswordArchived = { biometricsCache: { enabled: false, }, + notificationsCache: { + notificationDetailCache: null, + }, }; describe("Cards Details page - current not archived credential", () => { @@ -165,6 +172,9 @@ describe("Cards Details page - current not archived credential", () => { connectionsCache: { connections: [], }, + notificationsCache: { + notificationDetailCache: null, + }, }; storeMocked = { @@ -377,6 +387,9 @@ describe("Cards Details page - current not archived credential", () => { }, ], }, + notificationsCache: { + notificationDetailCache: null, + }, }; const storeMocked = { @@ -440,6 +453,10 @@ describe("Cards Details page - current not archived credential", () => { time: mockNow, })), }, + + notificationsCache: { + notificationDetailCache: null, + }, }; const storeMocked = { @@ -588,3 +605,83 @@ describe("Cards Details page - archived credential", () => { }); }); }); + +describe("Cred detail - notification light mode", () => { + let storeMocked: Store; + const credDispatchMock = jest.fn(); + + const state = { + stateCache: { + routes: [TabsRoutePath.CREDENTIALS], + authentication: { + loggedIn: true, + time: Date.now(), + passcodeIsSet: true, + passwordIsSet: false, + passwordIsSkipped: true, + }, + }, + seedPhraseCache: { + seedPhrase: + "example1 example2 example3 example4 example5 example6 example7 example8 example9 example10 example11 example12 example13 example14 example15", + bran: "bran", + }, + credsCache: { creds: credsFixAcdc }, + credsArchivedCache: { creds: [] }, + biometricsCache: { + enabled: false, + }, + notificationsCache: { + notificationDetailCache: { + notificationId: "test-id", + viewCred: "test-cred", + step: 0, + }, + }, + }; + + beforeAll(() => { + jest + .spyOn(Agent.agent.credentials, "getCredentialDetailsById") + .mockResolvedValue(credsFixAcdc[0]); + }); + beforeEach(() => { + const mockStore = configureStore(); + storeMocked = { + ...mockStore(state), + dispatch: credDispatchMock, + }; + }); + + test("It show notification cred mode", async () => { + const { getByTestId } = render( + + + + + + ); + + await waitFor(() => { + expect(getByTestId("notification-selected")).toBeVisible(); + }); + + act(() => { + fireEvent.click(getByTestId("tab-done-button")); + }); + + await waitFor(() => { + expect(credDispatchMock).toBeCalledWith( + setNotificationDetailCache({ + notificationId: "test-id", + viewCred: "test-cred", + step: 1, + checked: false, + }) + ); + }); + }); +}); diff --git a/src/ui/pages/CredentialDetails/CredentialDetails.tsx b/src/ui/pages/CredentialDetails/CredentialDetails.tsx index 4f6539f6f..aad48975d 100644 --- a/src/ui/pages/CredentialDetails/CredentialDetails.tsx +++ b/src/ui/pages/CredentialDetails/CredentialDetails.tsx @@ -1,52 +1,58 @@ -import { useHistory, useParams } from "react-router-dom"; import { IonButton, + IonCheckbox, IonIcon, IonSpinner, useIonViewWillEnter, } from "@ionic/react"; import { ellipsisVertical, heart, heartOutline } from "ionicons/icons"; import { useEffect, useState } from "react"; -import { TabLayout } from "../../components/layout/TabLayout"; -import { TabsRoutePath } from "../../../routes/paths"; +import { useHistory, useParams } from "react-router-dom"; +import { Agent } from "../../../core/agent/agent"; +import { MiscRecordId } from "../../../core/agent/agent.types"; +import { BasicRecord } from "../../../core/agent/records"; +import { ACDCDetails } from "../../../core/agent/services/credentialService.types"; import { i18n } from "../../../i18n"; -import { updateReduxState } from "../../../store/utils"; +import { getNextRoute } from "../../../routes/nextRoute"; +import { TabsRoutePath } from "../../../routes/paths"; import { useAppDispatch, useAppSelector } from "../../../store/hooks"; +import { + addFavouritesCredsCache, + getCredsCache, + getFavouritesCredsCache, + removeFavouritesCredsCache, + setCredsCache, +} from "../../../store/reducers/credsCache"; +import { + getNotificationDetailCache, + setNotificationDetailCache, +} from "../../../store/reducers/notificationsCache"; import { getStateCache, setCurrentOperation, setCurrentRoute, setToastMsg, } from "../../../store/reducers/stateCache"; -import { VerifyPassword } from "../../components/VerifyPassword"; +import { updateReduxState } from "../../../store/utils"; import { Alert as AlertDeleteArchive, Alert as AlertRestore, } from "../../components/Alert"; +import "../../components/CardDetails/CardDetails.scss"; +import { CredentialCardTemplate } from "../../components/CredentialCardTemplate"; import { CredentialOptions } from "../../components/CredentialOptions"; +import { TabLayout } from "../../components/layout/TabLayout"; +import { PageFooter } from "../../components/PageFooter"; +import { VerifyPasscode } from "../../components/VerifyPasscode"; +import { VerifyPassword } from "../../components/VerifyPassword"; import { MAX_FAVOURITES } from "../../globals/constants"; import { OperationType, ToastMsgType } from "../../globals/types"; -import { VerifyPasscode } from "../../components/VerifyPasscode"; -import { Agent } from "../../../core/agent/agent"; -import { - addFavouritesCredsCache, - getCredsCache, - getFavouritesCredsCache, - removeFavouritesCredsCache, - setCredsCache, -} from "../../../store/reducers/credsCache"; -import { getNextRoute } from "../../../routes/nextRoute"; -import { CredentialCardTemplate } from "../../components/CredentialCardTemplate"; -import { ACDCDetails } from "../../../core/agent/services/credentialService.types"; -import "../../components/CardDetails/CardDetails.scss"; -import "./CredentialDetails.scss"; -import { PageFooter } from "../../components/PageFooter"; -import { CredentialContent } from "./components/CredentialContent"; -import { combineClassNames } from "../../utils/style"; import { useAppIonRouter } from "../../hooks"; -import { MiscRecordId } from "../../../core/agent/agent.types"; -import { BasicRecord } from "../../../core/agent/records"; -import { setCredsArchivedCache } from "../../../store/reducers/credsArchivedCache"; +import { combineClassNames } from "../../utils/style"; +import { CredentialContent } from "./components/CredentialContent"; +import "./CredentialDetails.scss"; +import { CredHistory } from "./CredentialDetails.types"; +import { NotificationDetailCacheState } from "../../../store/reducers/notificationsCache/notificationCache.types"; const NAVIGATION_DELAY = 250; const CLEAR_ANIMATION = 1000; @@ -54,7 +60,7 @@ const CLEAR_ANIMATION = 1000; const CredentialDetails = () => { const pageId = "credential-card-details"; const ionRouter = useAppIonRouter(); - const history = useHistory(); + const history = useHistory(); const dispatch = useAppDispatch(); const credsCache = useAppSelector(getCredsCache); const favouritesCredsCache = useAppSelector(getFavouritesCredsCache); @@ -67,9 +73,13 @@ const CredentialDetails = () => { const [verifyPasscodeIsOpen, setVerifyPasscodeIsOpen] = useState(false); const params: { id: string } = useParams(); const [cardData, setCardData] = useState(); - const [navAnimation, setNavAnimation] = useState(false); + const notificationDetailCache = useAppSelector(getNotificationDetailCache); + const [notiSelected, setNotiSelected] = useState( + !!notificationDetailCache?.checked + ); + const isArchived = credsCache.filter((item) => item.id === params.id).length === 0; const isFavourite = favouritesCredsCache?.some((fav) => fav.id === params.id); @@ -89,9 +99,36 @@ const CredentialDetails = () => { setCardData(cardDetails); }; + const handleBackNotification = ( + notificationDetailCache: NotificationDetailCacheState + ) => { + dispatch( + setNotificationDetailCache({ + ...notificationDetailCache, + step: 1, + checked: notiSelected, + }) + ); + + const path = `${TabsRoutePath.NOTIFICATIONS}/${notificationDetailCache.notificationId}`; + + setTimeout(() => { + ionRouter.push(path, "back", "pop"); + }, NAVIGATION_DELAY); + + setTimeout(() => { + setNavAnimation(false); + }, CLEAR_ANIMATION); + }; + const handleDone = () => { setNavAnimation(true); + if (notificationDetailCache) { + handleBackNotification(notificationDetailCache); + return; + } + const { nextPath, updateRedux } = getNextRoute( TabsRoutePath.CREDENTIAL_DETAILS, { @@ -122,7 +159,7 @@ const CredentialDetails = () => { handleSetFavourite(params.id); } dispatch(setCredsCache(creds)); - + dispatch(setNotificationDetailCache(null)); dispatch(setToastMsg(ToastMsgType.CREDENTIAL_ARCHIVED)); }; @@ -168,7 +205,7 @@ const CredentialDetails = () => { .then(() => { dispatch(removeFavouritesCredsCache(id)); }) - .catch((error) => { + .catch(() => { /*TODO: handle error*/ }); } else { @@ -189,7 +226,7 @@ const CredentialDetails = () => { .then(() => { dispatch(addFavouritesCredsCache({ id, time: Date.now() })); }) - .catch((error) => { + .catch(() => { /*TODO: handle error*/ }); } @@ -206,6 +243,21 @@ const CredentialDetails = () => { }; const AdditionalButtons = () => { + if (notificationDetailCache) { + return ( + { + e.stopPropagation(); + setNotiSelected(e.detail.checked); + }} + /> + ); + } + return ( <>