Skip to content

Commit

Permalink
feat(ui): update credential detail
Browse files Browse the repository at this point in the history
  • Loading branch information
Vu Van Duc authored and Vu Van Duc committed Jul 16, 2024
1 parent 60cc4bf commit 58635bc
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 30 deletions.
11 changes: 11 additions & 0 deletions src/ui/pages/CredentialDetails/CredentialDetails.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
97 changes: 97 additions & 0 deletions src/ui/pages/CredentialDetails/CredentialDetails.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
removeFavouritesCredsCache,
setCredsCache,
} from "../../../store/reducers/credsCache";
import { setNotificationDetailCache } from "../../../store/reducers/notificationsCache";
import {
setCurrentRoute,
setToastMsg,
Expand Down Expand Up @@ -78,6 +79,9 @@ const initialStateNoPasswordCurrent = {
biometricsCache: {
enabled: false,
},
notificationsCache: {
notificationDetailCache: null,
},
};

const initialStateNoPasswordArchived = {
Expand All @@ -101,6 +105,9 @@ const initialStateNoPasswordArchived = {
biometricsCache: {
enabled: false,
},
notificationsCache: {
notificationDetailCache: null,
},
};

describe("Cards Details page - current not archived credential", () => {
Expand Down Expand Up @@ -165,6 +172,9 @@ describe("Cards Details page - current not archived credential", () => {
connectionsCache: {
connections: [],
},
notificationsCache: {
notificationDetailCache: null,
},
};

storeMocked = {
Expand Down Expand Up @@ -377,6 +387,9 @@ describe("Cards Details page - current not archived credential", () => {
},
],
},
notificationsCache: {
notificationDetailCache: null,
},
};

const storeMocked = {
Expand Down Expand Up @@ -440,6 +453,10 @@ describe("Cards Details page - current not archived credential", () => {
time: mockNow,
})),
},

notificationsCache: {
notificationDetailCache: null,
},
};

const storeMocked = {
Expand Down Expand Up @@ -588,3 +605,83 @@ describe("Cards Details page - archived credential", () => {
});
});
});

describe("Cred detail - notification light mode", () => {
let storeMocked: Store<unknown, AnyAction>;
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(
<Provider store={storeMocked}>
<MemoryRouter initialEntries={[path]}>
<Route
path={path}
component={CredentialDetails}
/>
</MemoryRouter>
</Provider>
);

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,
})
);
});
});
});
112 changes: 82 additions & 30 deletions src/ui/pages/CredentialDetails/CredentialDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,66 @@
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;

const CredentialDetails = () => {
const pageId = "credential-card-details";
const ionRouter = useAppIonRouter();
const history = useHistory();
const history = useHistory<CredHistory>();
const dispatch = useAppDispatch();
const credsCache = useAppSelector(getCredsCache);
const favouritesCredsCache = useAppSelector(getFavouritesCredsCache);
Expand All @@ -67,9 +73,13 @@ const CredentialDetails = () => {
const [verifyPasscodeIsOpen, setVerifyPasscodeIsOpen] = useState(false);
const params: { id: string } = useParams();
const [cardData, setCardData] = useState<ACDCDetails>();

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);
Expand All @@ -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,
{
Expand Down Expand Up @@ -122,7 +159,7 @@ const CredentialDetails = () => {
handleSetFavourite(params.id);
}
dispatch(setCredsCache(creds));

dispatch(setNotificationDetailCache(null));
dispatch(setToastMsg(ToastMsgType.CREDENTIAL_ARCHIVED));
};

Expand Down Expand Up @@ -168,7 +205,7 @@ const CredentialDetails = () => {
.then(() => {
dispatch(removeFavouritesCredsCache(id));
})
.catch((error) => {
.catch(() => {
/*TODO: handle error*/
});
} else {
Expand All @@ -189,7 +226,7 @@ const CredentialDetails = () => {
.then(() => {
dispatch(addFavouritesCredsCache({ id, time: Date.now() }));
})
.catch((error) => {
.catch(() => {
/*TODO: handle error*/
});
}
Expand All @@ -206,6 +243,21 @@ const CredentialDetails = () => {
};

const AdditionalButtons = () => {
if (notificationDetailCache) {
return (
<IonCheckbox
checked={notiSelected}
aria-label=""
className="notification-selected"
data-testid="notification-selected"
onIonChange={(e) => {
e.stopPropagation();
setNotiSelected(e.detail.checked);
}}
/>
);
}

return (
<>
<IonButton
Expand Down
5 changes: 5 additions & 0 deletions src/ui/pages/CredentialDetails/CredentialDetails.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { NotificationDetailState } from "../NotificationDetails/NotificationDetails.types";

type CredHistory = NotificationDetailState;

export type { CredHistory };

0 comments on commit 58635bc

Please sign in to comment.