From 438f1b06b996995a2c37bfff479079484e4240e7 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 22 Jun 2019 23:45:09 -0700 Subject: [PATCH] Add support for changing account password --- .../api/account/updateAccountPassword.ts | 2 +- .../scripts/components/FlashMessageRender.tsx | 12 +++++++--- .../account/AccountOverviewContainer.tsx | 2 +- .../account/forms/UpdatePasswordForm.tsx | 23 +++++++++++++++---- .../components/elements/ContentBox.tsx | 5 +++- resources/scripts/state/models/flashes.ts | 4 ++-- resources/scripts/state/types.d.ts | 3 ++- 7 files changed, 38 insertions(+), 13 deletions(-) diff --git a/resources/scripts/api/account/updateAccountPassword.ts b/resources/scripts/api/account/updateAccountPassword.ts index b2c3f10ba..c29aefd2d 100644 --- a/resources/scripts/api/account/updateAccountPassword.ts +++ b/resources/scripts/api/account/updateAccountPassword.ts @@ -8,7 +8,7 @@ interface Data { export default ({ current, password, confirmPassword }: Data): Promise => { return new Promise((resolve, reject) => { - http.put('/account/password', { + http.put('/api/client/account/password', { // eslint-disable-next-line @typescript-eslint/camelcase current_password: current, password: password, diff --git a/resources/scripts/components/FlashMessageRender.tsx b/resources/scripts/components/FlashMessageRender.tsx index ae9648784..5b9c51d75 100644 --- a/resources/scripts/components/FlashMessageRender.tsx +++ b/resources/scripts/components/FlashMessageRender.tsx @@ -4,14 +4,20 @@ import { State, useStoreState } from 'easy-peasy'; import { ApplicationState } from '@/state/types'; type Props = Readonly<{ + byKey?: string; spacerClass?: string; withBottomSpace?: boolean; }>; -export default ({ withBottomSpace, spacerClass }: Props) => { +export default ({ withBottomSpace, spacerClass, byKey }: Props) => { const flashes = useStoreState((state: State) => state.flashes.items); - if (flashes.length === 0) { + let filtered = flashes; + if (byKey) { + filtered = flashes.filter(flash => flash.key === byKey); + } + + if (filtered.length === 0) { return null; } @@ -19,7 +25,7 @@ export default ({ withBottomSpace, spacerClass }: Props) => { return (
{ - flashes.map((flash, index) => ( + filtered.map((flash, index) => ( {index > 0 &&
} diff --git a/resources/scripts/components/account/AccountOverviewContainer.tsx b/resources/scripts/components/account/AccountOverviewContainer.tsx index 158d30ed8..61174a548 100644 --- a/resources/scripts/components/account/AccountOverviewContainer.tsx +++ b/resources/scripts/components/account/AccountOverviewContainer.tsx @@ -5,7 +5,7 @@ import UpdatePasswordForm from '@/components/account/forms/UpdatePasswordForm'; export default () => { return (
- +
diff --git a/resources/scripts/components/account/forms/UpdatePasswordForm.tsx b/resources/scripts/components/account/forms/UpdatePasswordForm.tsx index d64faf4bf..dce13e650 100644 --- a/resources/scripts/components/account/forms/UpdatePasswordForm.tsx +++ b/resources/scripts/components/account/forms/UpdatePasswordForm.tsx @@ -1,10 +1,12 @@ -import React, { useState } from 'react'; -import { State, useStoreState } from 'easy-peasy'; +import React from 'react'; +import { Actions, State, useStoreActions, useStoreState } from 'easy-peasy'; import { ApplicationState } from '@/state/types'; import { Form, Formik, FormikActions } from 'formik'; import Field from '@/components/elements/Field'; import * as Yup from 'yup'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; +import updateAccountPassword from '@/api/account/updateAccountPassword'; +import { httpErrorToHuman } from '@/api/http'; interface Values { current: string; @@ -22,13 +24,26 @@ const schema = Yup.object().shape({ export default () => { const user = useStoreState((state: State) => state.user.data); + const { clearFlashes, addFlash } = useStoreActions((actions: Actions) => actions.flashes); if (!user) { return null; } - const submit = (values: Values, { setSubmitting }: FormikActions) => { - setTimeout(() => setSubmitting(false), 1500); + const submit = (values: Values, { resetForm, setSubmitting }: FormikActions) => { + clearFlashes('account:password'); + updateAccountPassword({ ...values }) + .then(() => { + resetForm(); + addFlash({ key: 'account:password', type: 'success', message: 'Your password has been updated.' }); + }) + .catch(error => addFlash({ + key: 'account:password', + type: 'error', + title: 'Error', + message: httpErrorToHuman(error), + })) + .then(() => setSubmitting(false)); }; return ( diff --git a/resources/scripts/components/elements/ContentBox.tsx b/resources/scripts/components/elements/ContentBox.tsx index 109d848a9..8fc74ea61 100644 --- a/resources/scripts/components/elements/ContentBox.tsx +++ b/resources/scripts/components/elements/ContentBox.tsx @@ -1,14 +1,17 @@ import * as React from 'react'; import classNames from 'classnames'; +import FlashMessageRender from '@/components/FlashMessageRender'; type Props = Readonly, HTMLDivElement> & { title?: string; borderColor?: string; + showFlashes?: string | boolean; }>; -export default ({ title, borderColor, children, ...props }: Props) => ( +export default ({ title, borderColor, showFlashes, children, ...props }: Props) => (
{title &&

{title}

} + {showFlashes && }
diff --git a/resources/scripts/state/models/flashes.ts b/resources/scripts/state/models/flashes.ts index 5c9a7f0a3..97c9f080b 100644 --- a/resources/scripts/state/models/flashes.ts +++ b/resources/scripts/state/models/flashes.ts @@ -6,8 +6,8 @@ const flashes: FlashState = { addFlash: action((state, payload) => { state.items.push(payload); }), - clearFlashes: action(state => { - state.items = []; + clearFlashes: action((state, payload) => { + state.items = payload ? state.items.filter(flashes => flashes.key !== payload) : []; }), }; diff --git a/resources/scripts/state/types.d.ts b/resources/scripts/state/types.d.ts index 7c700a692..644a4679f 100644 --- a/resources/scripts/state/types.d.ts +++ b/resources/scripts/state/types.d.ts @@ -9,7 +9,7 @@ export interface ApplicationState { export interface FlashState { items: FlashMessage[]; addFlash: Action; - clearFlashes: Action; + clearFlashes: Action; } export interface UserState { @@ -30,6 +30,7 @@ export interface UserData { export interface FlashMessage { id?: string; + key?: string; type: FlashMessageType; title?: string; message: string;