Skip to content

Commit

Permalink
SDP-877: Retry invitation SMS (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
ceciliaromao authored Oct 6, 2023
1 parent 1020c32 commit cce74c0
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 25 deletions.
19 changes: 19 additions & 0 deletions src/api/retryInvitationSMS.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { handleApiResponse } from "api/handleApiResponse";
import { API_URL } from "constants/settings";

export const retryInvitationSMS = async (
token: string,
receiverWalletId: string,
): Promise<{ message: string }> => {
const response = await fetch(
`${API_URL}/receivers/wallets/${receiverWalletId}`,
{
method: "PATCH",
headers: {
Authorization: `Bearer ${token}`,
},
},
);

return handleApiResponse(response);
};
2 changes: 1 addition & 1 deletion src/generated/gitInfo.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export default { commitHash: "4aaf371", version: "1.0.0-rc2-21-g4aaf371" };
export default { commitHash: "d13cf63", version: "1.0.0-rc2-10-gd13cf63" };
106 changes: 83 additions & 23 deletions src/pages/ReceiverDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import {
} from "@stellar/design-system";

import { AppDispatch } from "store";
import { getReceiverDetailsAction } from "store/ducks/receiverDetails";
import {
getReceiverDetailsAction,
resetRetryStatusAction,
retryInvitationSMSAction,
} from "store/ducks/receiverDetails";
import {
getReceiverPaymentsAction,
getReceiverPaymentsWithParamsAction,
Expand All @@ -28,6 +32,7 @@ import { PaymentsTable } from "components/PaymentsTable";
import { Pagination } from "components/Pagination";
import { ReceiverWalletBalance } from "components/ReceiverWalletBalance";
import { ReceiverWalletHistory } from "components/ReceiverWalletHistory";
import { NotificationWithButtons } from "components/NotificationWithButtons";

import { number, percent } from "helpers/formatIntlNumber";
import { renderNumberOrDash } from "helpers/renderNumberOrDash";
Expand Down Expand Up @@ -125,6 +130,10 @@ export const ReceiverDetails = () => {
handlePageChange(newPage);
};

const handleRetryInvitation = (receiverWalletId: string) => {
dispatch(retryInvitationSMSAction({ receiverWalletId }));
};

const setCardTemplateRows = (rows: number) => {
return {
"--StatCard-template-rows": rows,
Expand Down Expand Up @@ -256,28 +265,76 @@ export const ReceiverDetails = () => {
const renderWallets = () => {
return (
<div className="ReceiverDetails__wallets">
<div className="ReceiverDetails__wallets__dropdown">
<Select
fieldSize="sm"
id="receiver-wallets"
value={selectedWallet?.id}
onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>
setSelectedWallet(
receiverDetails.wallets.find(
(w) => w.id === event.currentTarget.value,
),
)
}
{receiverDetails.retryInvitationStatus === "SUCCESS" && (
<NotificationWithButtons
variant="success"
title="SMS invitation sent successfully!"
buttons={[
{
label: "Dismiss",
onClick: () => {
dispatch(resetRetryStatusAction());
},
},
]}
>
{receiverDetails.wallets.map((w) => (
<option key={w.id} value={w.id}>
{renderWalletOptionText(w)}
</option>
))}
</Select>

<div className="ReceiverDetails__wallets__subtitle">
{renderTitle(receiverDetails.wallets.length, "wallet", "wallets")}
{" "}
</NotificationWithButtons>
)}
{receiverDetails.retryInvitationStatus === "ERROR" && (
<NotificationWithButtons
variant="error"
title="Error"
buttons={[
{
label: "Dismiss",
onClick: () => {
dispatch(resetRetryStatusAction());
},
},
]}
>
{receiverDetails.errorString}
</NotificationWithButtons>
)}
<div className="ReceiverDetails__wallets__row">
<div className="ReceiverDetails__wallets__dropdown">
<Select
fieldSize="sm"
id="receiver-wallets"
value={selectedWallet?.id}
onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>
setSelectedWallet(
receiverDetails.wallets.find(
(w) => w.id === event.currentTarget.value,
),
)
}
>
{receiverDetails.wallets.map((w) => (
<option key={w.id} value={w.id}>
{renderWalletOptionText(w)}
</option>
))}
</Select>

<div className="ReceiverDetails__wallets__subtitle">
{renderTitle(receiverDetails.wallets.length, "wallet", "wallets")}
</div>
</div>

<div>
<Button
variant="secondary"
size="xs"
type="reset"
onClick={(e) => {
e.preventDefault();
handleRetryInvitation(selectedWallet?.id || "");
}}
>
Retry Invitation SMS
</Button>
</div>
</div>

Expand Down Expand Up @@ -422,7 +479,10 @@ export const ReceiverDetails = () => {
};

const renderContent = () => {
if (receiverDetails.errorString) {
if (
receiverDetails.errorString &&
receiverDetails.retryInvitationStatus !== "ERROR"
) {
return (
<Notification variant="error" title="Error">
{receiverDetails.errorString}
Expand Down
48 changes: 47 additions & 1 deletion src/store/ducks/receiverDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { RootState } from "store";
import { getReceiverDetails } from "api/getReceiverDetails";
import { patchReceiverInfo } from "api/patchReceiver";
import { retryInvitationSMS } from "api/retryInvitationSMS";
import { handleApiErrorString } from "api/handleApiErrorString";
import { endSessionIfTokenInvalid } from "helpers/endSessionIfTokenInvalid";
import { refreshSessionToken } from "helpers/refreshSessionToken";
Expand Down Expand Up @@ -69,6 +70,31 @@ export const updateReceiverDetailsAction = createAsyncThunk<
},
);

export const retryInvitationSMSAction = createAsyncThunk<
string,
{ receiverWalletId: string },
{ rejectValue: RejectMessage; state: RootState }
>(
"receiverDetails/retryInvitationSMSAction",
async ({ receiverWalletId }, { rejectWithValue, getState, dispatch }) => {
const { token } = getState().userAccount;

try {
const response = await retryInvitationSMS(token, receiverWalletId);
return response.message;
} catch (error: unknown) {
const err = error as ApiError;
const errorString = handleApiErrorString(err);
endSessionIfTokenInvalid(errorString, dispatch);

return rejectWithValue({
errorString: `Error retrying invitation: ${errorString}`,
errorExtras: err?.extras,
});
}
},
);

const initialState: ReceiverDetailsInitialState = {
id: "",
phoneNumber: "",
Expand Down Expand Up @@ -104,6 +130,7 @@ const initialState: ReceiverDetailsInitialState = {
],
status: undefined,
updateStatus: undefined,
retryInvitationStatus: undefined,
errorString: undefined,
};

Expand All @@ -112,6 +139,9 @@ const receiverDetailsSlice = createSlice({
initialState,
reducers: {
resetReceiverDetailsAction: () => initialState,
resetRetryStatusAction: (state) => {
state.retryInvitationStatus = undefined;
},
},
extraReducers: (builder) => {
// Get receiver details
Expand Down Expand Up @@ -153,13 +183,29 @@ const receiverDetailsSlice = createSlice({
state.updateStatus = "ERROR";
state.errorString = action.payload?.errorString;
});
//retryInvitationSMSAction
builder.addCase(
retryInvitationSMSAction.pending,
(state = initialState) => {
state.retryInvitationStatus = "PENDING";
},
);
builder.addCase(retryInvitationSMSAction.fulfilled, (state) => {
state.retryInvitationStatus = "SUCCESS";
state.errorString = undefined;
});
builder.addCase(retryInvitationSMSAction.rejected, (state, action) => {
state.retryInvitationStatus = "ERROR";
state.errorString = action.payload?.errorString;
});
},
});

export const receiverDetailsSelector = (state: RootState) =>
state.receiverDetails;
export const { reducer } = receiverDetailsSlice;
export const { resetReceiverDetailsAction } = receiverDetailsSlice.actions;
export const { resetReceiverDetailsAction, resetRetryStatusAction } =
receiverDetailsSlice.actions;

const formatReceiver = (receiver: ApiReceiver): ReceiverDetails => ({
id: receiver.id,
Expand Down
6 changes: 6 additions & 0 deletions src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,12 @@ body {
margin-bottom: pxToRem(12px);
}

&__row {
display: flex;
justify-content: space-between;
align-items: center;
}

&__dropdown {
display: flex;
align-items: center;
Expand Down
1 change: 1 addition & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export type ReceiverDetailsInitialState = {
verifications: ReceiverVerification[];
status: ActionStatus | undefined;
updateStatus: ActionStatus | undefined;
retryInvitationStatus: ActionStatus | undefined;
errorString?: string;
};

Expand Down

0 comments on commit cce74c0

Please sign in to comment.