Skip to content

Commit

Permalink
Add phone field to profile (#774)
Browse files Browse the repository at this point in the history
  • Loading branch information
kaol authored Oct 8, 2021
1 parent 12d68df commit 9f56c4f
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 7 deletions.
2 changes: 1 addition & 1 deletion apps/mosaico/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"cheerio": "^1.0.0-rc.10",
"parcel": "1.12.3",
"parcel-bundler": "^1.12.3",
"persona": "https://github.com/KSF-Media/persona-javascript-client.git#40058b09b6d969390daaad6e58918b04129b1c16",
"persona": "https://github.com/KSF-Media/persona-javascript-client.git#d8876dc53c39e6c80cdff363a8230deb944c6e73",
"react": ">=16.12",
"react-date-picker": "^8.0.3",
"react-dom": ">=16.12",
Expand Down
8 changes: 7 additions & 1 deletion packages/components/src/Persona.purs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ updateUser uuid update auth = do
let body = case update of
UpdateName names -> unsafeToForeign names
UpdateEmail email -> unsafeToForeign email
UpdatePhone phone -> unsafeToForeign phone
UpdateAddress { countryCode, zipCode, streetAddress, startDate } ->
unsafeToForeign
{ address:
Expand All @@ -96,6 +97,7 @@ updateUser uuid update auth = do
unsafeToForeign
{ firstName: userInfo.firstName
, lastName: userInfo.lastName
, phone: toNullable $ userInfo.phone
, address:
{ streetAddress: userInfo.streetAddress
, zipCode: userInfo.zipCode
Expand Down Expand Up @@ -203,8 +205,9 @@ hasScope :: UUID -> AuthScope -> UserAuth -> Aff Number
hasScope uuid authScope auth = do
callApi usersApi "usersUuidScopeGet"
[ unsafeToForeign uuid
, unsafeToForeign scope
] $
Record.merge ( authHeaders uuid auth ) { scope }
( authHeaders uuid auth )
where
scope = case authScope of
UserRead -> "UserRead"
Expand Down Expand Up @@ -356,6 +359,7 @@ type LoginDataSso =
data UserUpdate
= UpdateName { firstName :: String, lastName :: String }
| UpdateEmail { email :: String }
| UpdatePhone { phone :: String }
| UpdateAddress { countryCode :: String
, zipCode :: String
, streetAddress :: String
Expand All @@ -367,6 +371,7 @@ data UserUpdate
, countryCode :: String
, zipCode :: String
, streetAddress :: String
, phone :: Maybe String
, startDate :: Maybe Date
}
| DeletePendingAddressChanges
Expand Down Expand Up @@ -479,6 +484,7 @@ type BaseUser =
, firstName :: Nullable String
, lastName :: Nullable String
, address :: Nullable Address
, phone :: Nullable String
, cusno :: Cusno
, subs :: Array Subscription
, consent :: Array GdprConsent
Expand Down
114 changes: 112 additions & 2 deletions packages/components/src/Profile/Component.purs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import KSF.Sentry as Sentry
import KSF.User (User, UserError(UniqueViolation))
import KSF.User as User
import KSF.User.Cusno as Cusno
import KSF.ValidatableForm (class ValidatableField, ValidatedForm, inputFieldErrorMessage, validateEmailAddress, validateEmptyField, validateField, validateFinnishZipCode, validateZipCode)
import KSF.ValidatableForm (class ValidatableField, ValidatedForm, inputFieldErrorMessage, validateEmailAddress, validateEmptyField, validateField, validatePhone, validateFinnishZipCode, validateZipCode)
import React.Basic (JSX)
import React.Basic.Classic (make)
import React.Basic.Classic as React
Expand All @@ -59,11 +59,13 @@ type State =
{ name :: Name
, address :: Address
, email :: Maybe String
, phone :: Maybe String
, now :: Maybe Date
, changeDate :: Maybe Date
, editFields :: Set EditField
, editName :: AsyncWrapper.Progress JSX
, editEmail :: AsyncWrapper.Progress JSX
, editPhone :: AsyncWrapper.Progress JSX
, editAddress :: AsyncWrapper.Progress JSX
}

Expand All @@ -79,7 +81,7 @@ type Address =
, city :: Maybe String
}

data EditField = EditAddress | EditEmail | EditName
data EditField = EditAddress | EditEmail | EditName | EditPhone
derive instance eqEditField :: Eq EditField
derive instance ordEditField :: Ord EditField

Expand Down Expand Up @@ -113,6 +115,12 @@ instance validatableFieldEmailFormFields :: ValidatableField EmailFormFields whe
validateField field value _serverErrors = case field of
Email -> validateEmailAddress field value

data PhoneFormFields
= Phone
instance validatableFieldPhoneFormFields :: ValidatableField PhoneFormFields where
validateField field value _serverErrors = case field of
Phone -> validatePhone field value

derive instance eqEmailFormFields :: Eq EmailFormFields

jsComponent :: React.Component Props
Expand All @@ -126,12 +134,14 @@ profile = make component
{ initialState:
{ name: { firstName: Nothing, lastName: Nothing }
, email: Nothing
, phone: Nothing
, address: { zipCode: Nothing, countryCode: Nothing, streetAddress: Nothing, city: Nothing }
, now: Nothing
, changeDate: Nothing
, editFields: Set.empty
, editName: Ready
, editEmail: Ready
, editPhone: Ready
, editAddress: Ready
}
, render
Expand All @@ -150,6 +160,7 @@ didMount self = do
resetFields self EditEmail
resetFields self EditAddress
resetFields self EditName
resetFields self EditPhone

render :: Self -> JSX
render self@{ props: { profile: user } } =
Expand All @@ -164,6 +175,7 @@ render self@{ props: { profile: user } } =
[ DescriptionList.descriptionList { definitions: visiblePendingAddressChanges } ]
}
, profileEmail
, profilePhone
, DOM.div
{ id: "profile--display"
, children:
Expand Down Expand Up @@ -220,6 +232,49 @@ render self@{ props: { profile: user } } =
]
}

profilePhone =
AsyncWrapper.asyncWrapper
{ wrapperState: self.state.editPhone
, readyView: profilePhoneReady
, editingView: \_ -> profilePhoneEditing
, loadingView: profilePhoneLoading
, successView: \_ -> profilePhoneReady
, errorView: editingError self EditPhone
}
where
profilePhoneReady = DOM.div
{ className: "profile--profile-row"
, id: "profile--phone"
, children:
[ currentPhone
, changePhoneButton self
]
}
profilePhoneEditing = DOM.div_
[ DescriptionList.descriptionList
{ definitions:
[ { term: "Telefonnummer:"
, description: [ editPhone self ]
}
]
}
]
profilePhoneLoading spinner = DOM.div
{ className: "profile--profile-row"
, children:
[ currentPhone
, spinner
]
}
currentPhone =
DescriptionList.descriptionList
{ definitions:
[ { term: "Telefonnummer:"
, description: [ DOM.text $ fromMaybe "-" $ Nullable.toMaybe user.phone ]
}
]
}

profileName =
AsyncWrapper.asyncWrapper
{ wrapperState: self.state.editName
Expand Down Expand Up @@ -329,6 +384,7 @@ editingError self fieldName errMessage =
EditAddress -> self.setState _ { editAddress = AsyncWrapper.Ready }
EditName -> self.setState _ { editName = AsyncWrapper.Ready }
EditEmail -> self.setState _ { editEmail = AsyncWrapper.Ready }
EditPhone -> self.setState _ { editPhone = AsyncWrapper.Ready }
}
]
}
Expand Down Expand Up @@ -502,6 +558,53 @@ editEmail self =
Tracking.changeEmail self.props.profile.cusno "error: unexpected error when updating email"
updateEmail _ = pure unit

editPhone :: Self -> JSX
editPhone self =
DOM.form
{ className: "profile--edit-phone"
, children:
[ InputField.inputField
{ type_: InputField.Text
, name: "phone"
, placeholder: "Telefonnummer"
, value: self.state.phone
, onChange: \newPhone -> self.setState _ { phone = newPhone }
, label: Just "Telefonnummer"
, validationError: inputFieldErrorMessage $ validateField Phone self.state.phone []
}
, submitButton
, DOM.div { className: "profile--submit-buttons", children: [ iconClose self EditPhone ] }
]
, onSubmit: Events.handler preventDefault $ \_ -> submitNewPhone $ validatePhoneForm self.state.phone
}
where
submitButton = iconSubmit $ isValid (validatePhoneForm self.state.phone)

validatePhoneForm :: Maybe String -> ValidatedForm PhoneFormFields (Maybe String)
validatePhoneForm form =
validateField Phone form []

submitNewPhone :: ValidatedForm PhoneFormFields (Maybe String) -> Effect Unit
submitNewPhone = validation
(\_ -> Console.error "Could not submit phone.")
updatePhone

updatePhone :: Maybe String -> Effect Unit
updatePhone (Just phone) = do
self.setState _ { editPhone = Loading mempty }
Aff.launchAff_ do
newUser <- User.updateUser self.props.profile.uuid $ User.UpdatePhone { phone }
case newUser of
Right u -> liftEffect do
self.props.onUpdate u
self.setState _ { editEmail = Success Nothing }
Tracking.changePhone self.props.profile.cusno "success"
Left err -> liftEffect do
self.props.logger.error $ Error.userError $ show err
self.setState _ { editPhone = AsyncWrapper.Error "Det gick inte att updatera telefonnummer. Vänligen tak kontakt med kundservice." }
Tracking.changePhone self.props.profile.cusno "error: unexpected error when updating phone"
updatePhone _ = pure unit

editName :: Self -> JSX
editName self =
DOM.form
Expand Down Expand Up @@ -631,6 +734,9 @@ changeEmailButton self = changeAttributeButton self EditEmail
changeNameButton :: Self -> JSX
changeNameButton self = changeAttributeButton self EditName

changePhoneButton :: Self -> JSX
changePhoneButton self = changeAttributeButton self EditPhone

editButton :: String -> Self -> EditField -> JSX
editButton buttonText self field =
DOM.div
Expand All @@ -657,6 +763,7 @@ switchEditProgress :: Self -> EditField -> AsyncWrapper.Progress JSX -> Effect U
switchEditProgress self EditName progress = self.setState _ { editName = progress }
switchEditProgress self EditEmail progress = self.setState _ { editEmail = progress }
switchEditProgress self EditAddress progress = self.setState _ { editAddress = progress }
switchEditProgress self EditPhone progress = self.setState _ { editPhone = progress }

isUpcomingPendingChange :: Maybe Date -> User.PendingAddressChange -> Boolean
isUpcomingPendingChange Nothing _ = true
Expand Down Expand Up @@ -688,6 +795,9 @@ resetFields self EditName =
resetFields self EditEmail =
self.setState _ { email = Just self.props.profile.email }

resetFields self EditPhone =
self.setState _ { phone = Nullable.toMaybe self.props.profile.phone }

formatAddress :: User.DeliveryAddress -> String
formatAddress { temporaryName, streetAddress, zipcode, city } =
(maybe "" (_ <> ", ") $ toMaybe temporaryName) <>
Expand Down
4 changes: 4 additions & 0 deletions packages/components/src/Tracking.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ exports.changeAddress_ = function (cusno, result) {
dataLayer.push({ event: "changeAddress", cusno: cusno, result: result });
};

exports.changePhone_ = function (cusno, result) {
dataLayer.push({ event: "changePhone", cusno: cusno, result: result });
};

exports.deletePendingAddressChanges_ = function (cusno, result) {
dataLayer.push({ event: "deletePendingAddressChanges", cusno: cusno, result: result });
};
Expand Down
4 changes: 4 additions & 0 deletions packages/components/src/Tracking.purs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ foreign import updateCreditCard_ :: EffectFn5 Cusno Subsno CreditCard CreditCard
foreign import changeName_ :: EffectFn2 Cusno Result Unit
foreign import changeEmail_ :: EffectFn2 Cusno Result Unit
foreign import changeAddress_ :: EffectFn2 Cusno Result Unit
foreign import changePhone_ :: EffectFn2 Cusno Result Unit
foreign import deletePendingAddressChanges_ :: EffectFn2 Cusno Result Unit
foreign import updateResetPassword_ :: EffectFn1 Result Unit

Expand Down Expand Up @@ -94,6 +95,9 @@ changeEmail = runEffectFn2 changeEmail_
changeAddress :: Cusno -> Result -> Effect Unit
changeAddress = runEffectFn2 changeAddress_

changePhone :: Cusno -> Result -> Effect Unit
changePhone = runEffectFn2 changePhone_

deletePendingAddressChanges :: Cusno -> Result -> Effect Unit
deletePendingAddressChanges = runEffectFn2 deletePendingAddressChanges_

Expand Down
2 changes: 1 addition & 1 deletion packages/user/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "index.js",
"license": "MIT",
"dependencies": {
"persona": "https://github.com/KSF-Media/persona-javascript-client.git#40058b09b6d969390daaad6e58918b04129b1c16",
"persona": "https://github.com/KSF-Media/persona-javascript-client.git#d8876dc53c39e6c80cdff363a8230deb944c6e73",
"react": "^16.12",
"bottega": "https://github.com/KSF-Media/bottega-javascript-client.git#f58baa4ebf8a494347b212e3378b6168c5e2faff",
"react-dom": "^16.12"
Expand Down
2 changes: 1 addition & 1 deletion packages/vetrina/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"@sentry/browser": "^6.2.1",
"bottega": "https://github.com/KSF-Media/bottega-javascript-client.git#f58baa4ebf8a494347b212e3378b6168c5e2faff",
"create-react-class": "^15.6.3",
"persona": "https://github.com/KSF-Media/persona-javascript-client.git#40058b09b6d969390daaad6e58918b04129b1c16",
"persona": "https://github.com/KSF-Media/persona-javascript-client.git#d8876dc53c39e6c80cdff363a8230deb944c6e73",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"uuid-validate": "^0.0.3"
Expand Down
2 changes: 1 addition & 1 deletion packages/vetrina/src/Vetrina/Purchase/AccountForm.purs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ render props self@{ state: { contactForm } } = fragment
liftEffect $ props.setLoading (Just Spinner.Loading)
Aff.finally
(liftEffect $ props.setLoading Nothing)
do eitherUser <- User.updateUser props.user.uuid $ UpdateFull $ addr `merge` { startDate: Nothing }
do eitherUser <- User.updateUser props.user.uuid $ UpdateFull $ addr `merge` { startDate: Nothing, phone: Nothing }
case eitherUser of
Right user -> liftEffect $ props.retryPurchase user
Left err -> liftEffect $ props.onError err
Expand Down

0 comments on commit 9f56c4f

Please sign in to comment.