Skip to content

Commit 83efaf4

Browse files
committed
[Feature] Add failed address verification popup
Problem: We want to clarify the failed address error message better. Solution: - Add failed address verification popup instead of error message - Adjust other code accordingly
1 parent c05be9c commit 83efaf4

File tree

3 files changed

+150
-23
lines changed

3 files changed

+150
-23
lines changed

client/src/Checkout/View.elm

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
module Checkout.View exposing (PopupConfig, TextData, addPopupContainerView, failedAddressVerificationPopupView, textData)
2+
3+
import Components.Address.Address as Address
4+
import Components.Button as Button exposing (defaultButton)
5+
import Data.Locations exposing (AddressLocations)
6+
import Html exposing (..)
7+
import Html.Attributes exposing (..)
8+
9+
10+
11+
---------------------------------------------------------
12+
-- Types
13+
---------------------------------------------------------
14+
15+
16+
type alias PopupConfig msg =
17+
{ onEdit : msg
18+
, onContinue : msg
19+
, address : Address.Form
20+
, locations : AddressLocations
21+
}
22+
23+
24+
type alias TextData =
25+
{ title : String
26+
, descriptionLine1 : String
27+
, descriptionLine2 : String
28+
, shippingDetailsHeader : String
29+
, editAddressLabel : String
30+
, continueAnywayLabelMobile : String
31+
, continueAnywayLabelDesktop : String
32+
}
33+
34+
35+
textData : TextData
36+
textData =
37+
{ title = "We couldn't automatically verify this address"
38+
, descriptionLine1 = "An unverified address is not necessarily incorrect, but it may cause delivery issues."
39+
, descriptionLine2 = "Please check the address again or continue if you're sure it's correct."
40+
, shippingDetailsHeader = "Shipping Details"
41+
, editAddressLabel = "Edit address"
42+
, continueAnywayLabelMobile = "Continue"
43+
, continueAnywayLabelDesktop = "Continue anyway"
44+
}
45+
46+
47+
48+
---------------------------------------------------------
49+
-- Views
50+
---------------------------------------------------------
51+
52+
53+
addPopupContainerView : Html msg -> Html msg
54+
addPopupContainerView content =
55+
div [ class "tw:fixed tw:inset-0 tw:z-50 tw:flex tw:items-center tw:justify-center tw:bg-[#1E0C03]/50 tw:p-[16px]" ]
56+
[ content ]
57+
58+
59+
failedAddressVerificationPopupView : PopupConfig msg -> Html msg
60+
failedAddressVerificationPopupView config =
61+
div [ class "tw:relative tw:w-full tw:max-w-[696px] tw:rounded-[16px] tw:bg-white tw:p-[32px] tw:shadow-xl" ]
62+
[ -- Title
63+
div [ class "tw:pb-[24px] tw:pr-[24px]" ]
64+
[ h2 [ class "tw:!text-[24px] tw:!font-[600] tw:!leading-[32px] tw:!text-[#1E0C03]" ]
65+
[ text textData.title ]
66+
]
67+
68+
-- Description
69+
, div [ class "tw:pb-[16px]" ]
70+
[ p [ class "tw:!text-[16px] tw:!font-[400] tw:!leading-[24px] tw:!text-[#1E0C03]" ]
71+
[ text textData.descriptionLine1
72+
, br [] []
73+
, strong [ class "tw:!font-[600]" ] [ text textData.descriptionLine2 ]
74+
]
75+
]
76+
77+
-- Shipping Details Box
78+
, div [ class "tw:pb-[32px]" ]
79+
[ div [ class "tw:rounded-[8px] tw:bg-[#F9F9F9] tw:p-[24px]" ]
80+
[ div [ class "tw:pb-[16px]" ]
81+
[ h3 [ class "tw:!text-[14px] tw:!font-[400] tw:opacity-70" ] [ text textData.shippingDetailsHeader ] ]
82+
, div [ class "tw:text-[16px] tw:leading-[24px] tw:text-[#1E0C03]" ]
83+
[ Address.card config.address.model config.locations ]
84+
]
85+
]
86+
87+
-- Actions
88+
, div [ class "tw:flex tw:gap-[12px] tw:justify-center" ]
89+
[ Button.view
90+
{ defaultButton
91+
| label = textData.editAddressLabel
92+
, style = Button.Outline
93+
, type_ = Button.TriggerMsg config.onEdit
94+
, size = Button.Large
95+
, padding = Button.Width "tw:w-1/2 tw:lg:w-[194px]"
96+
}
97+
, Button.view
98+
{ defaultButton
99+
| label = ""
100+
, icon =
101+
Just <|
102+
div []
103+
[ span [ class "tw:inline tw:lg:hidden" ] [ text textData.continueAnywayLabelMobile ]
104+
, span [ class "tw:hidden tw:lg:inline" ] [ text textData.continueAnywayLabelDesktop ]
105+
]
106+
, style = Button.Solid
107+
, type_ = Button.TriggerMsg config.onContinue
108+
, size = Button.Large
109+
, padding = Button.Width "tw:w-1/2 tw:lg:w-[194px]"
110+
}
111+
]
112+
]

client/src/Pages/Checkout.elm

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module Pages.Checkout exposing
1313
, view
1414
)
1515

16+
import Checkout.View as CheckoutView
1617
import Components.Address.Address as Address exposing (AddressId(..))
1718
import Components.Alert as Alert exposing (defaultAlert)
1819
import Components.Aria as Aria
@@ -225,6 +226,8 @@ type Msg
225226
| ValidateCart
226227
| ValidateCartResponse (WebData (Result Api.FormErrors PageData.CartDetails))
227228
| GoBack
229+
| CloseVerifyAddressPopup
230+
| NoOp
228231

229232

230233
type alias CartInventoryNotifications =
@@ -746,6 +749,12 @@ update msg postgridApiKey model authStatus maybeSessionToken checkoutDetails =
746749
GoBack ->
747750
( model, Nothing, historyBack () )
748751

752+
CloseVerifyAddressPopup ->
753+
( { model | errors = Api.initialErrors }, Nothing, Ports.scrollToTop )
754+
755+
NoOp ->
756+
model |> nothingAndNoCommand
757+
749758

750759
selectAddress : Int -> CheckoutAddress
751760
selectAddress addressId =
@@ -1268,7 +1277,7 @@ helcimValidateCheckoutResultHandler model authStatus maybeSessionToken result =
12681277
RemoteData.Success (Ok res) ->
12691278
case res of
12701279
CheckoutSuccess token ->
1271-
( { model | checkoutToken = Just token.checkoutToken }
1280+
( { model | checkoutToken = Just token.checkoutToken, errors = Api.initialErrors, isValidating = False }
12721281
, Nothing
12731282
, Cmd.batch [ Ports.appendHelcimPayIframe token.checkoutToken, Ports.subscribeToHelcimMessages () ]
12741283
)
@@ -1312,7 +1321,7 @@ stripeValidateCheckoutResultHandler model authStatus maybeSessionToken details r
13121321
RemoteData.Success (Ok res) ->
13131322
case res of
13141323
CheckoutSuccess _ ->
1315-
( { model | isValidating = False }
1324+
( { model | isValidating = False, errors = Api.initialErrors }
13161325
, Nothing
13171326
, Ports.collectStripeToken ( customerEmail, finalTotal )
13181327
)
@@ -1659,6 +1668,14 @@ view model authStatus locations checkoutDetails =
16591668
else
16601669
text ""
16611670

1671+
addrErrors addr =
1672+
case addr of
1673+
ExistingAddress _ ->
1674+
Dict.empty
1675+
1676+
NewAddress addrForm ->
1677+
addrForm.errors
1678+
16621679
hasErrors =
16631680
not <|
16641681
Dict.isEmpty model.errors
@@ -1674,28 +1691,26 @@ view model authStatus locations checkoutDetails =
16741691
False
16751692

16761693
shippingAddressVerificationErrorsView =
1694+
let
1695+
shippingAddressForm =
1696+
case model.shippingAddress of
1697+
NewAddress form ->
1698+
form
1699+
1700+
ExistingAddress id ->
1701+
findBy (\a -> a.id == Just id) checkoutDetails.shippingAddresses
1702+
|> Maybe.map Address.fromModel
1703+
|> Maybe.withDefault Address.initialForm
1704+
in
16771705
viewIf hasShippingAddressVerificationErrors <|
1678-
div [ class "tw:pb-[16px]" ]
1679-
[ Alert.view
1680-
{ defaultAlert
1681-
| content =
1682-
div [ class "tw:text-[#bd8e00]" ]
1683-
[ p [ class "tw:font-semibold" ] [ text "We failed to verify your shipping address." ]
1684-
, br [] []
1685-
, p [] [ text "Please double-check your details." ]
1686-
, p [] [ text "If the address is correct, proceed with the checkout." ]
1687-
]
1688-
, style = Alert.Warning
1706+
(CheckoutView.addPopupContainerView <|
1707+
CheckoutView.failedAddressVerificationPopupView
1708+
{ onEdit = CloseVerifyAddressPopup
1709+
, onContinue = Submit Stripe
1710+
, address = shippingAddressForm
1711+
, locations = locations
16891712
}
1690-
]
1691-
1692-
addrErrors addr =
1693-
case addr of
1694-
ExistingAddress _ ->
1695-
Dict.empty
1696-
1697-
NewAddress addrForm ->
1698-
addrForm.errors
1713+
)
16991714

17001715
guestCard =
17011716
case authStatus of

0 commit comments

Comments
 (0)