Skip to content

Commit

Permalink
Renew subscriptions
Browse files Browse the repository at this point in the history
Closes: #546
  • Loading branch information
kaol committed Jun 17, 2021
1 parent 1e5bd1c commit 442d1c3
Show file tree
Hide file tree
Showing 14 changed files with 728 additions and 187 deletions.
13 changes: 12 additions & 1 deletion apps/mitt-konto/src/MittKonto/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import MittKonto.Main.CreditCardUpdateView (creditCardUpdateView) as CreditCardU
import MittKonto.Main.Elements as Elements
import MittKonto.Main.Helpers as Helpers
import MittKonto.Main.Types as Types
import MittKonto.Main.UserView.Subscription.Renew as RenewSubscription
import MittKonto.Main.Views (alertView, footerView, loginView, navbarView, userView) as Views
import MittKonto.Payment.PaymentAccordion as PaymentAccordion
import MittKonto.Payment.PaymentDetail as PaymentDetail
Expand All @@ -45,6 +46,7 @@ type ViewComponents =
, paymentDetailView :: JSX
, creditCardUpdateView :: User.User -> JSX
, passwordResetView :: JSX
, userView :: User.User -> JSX
, needRootRedirect :: Boolean
}

Expand All @@ -58,6 +60,8 @@ app = do
creditCardUpdate <- Wrappers.routeWrapper CreditCardUpdateView.creditCardUpdateView
now <- Now.nowDate
loginComponent <- Login.login
renewSubscriptionView <- RenewSubscription.renewSubscription
userViewComponent <- Views.userView logger renewSubscriptionView
location <- HTML.location =<< HTML.window
initialHash <- HTML.hash location
let initialState =
Expand Down Expand Up @@ -150,12 +154,19 @@ app = do
, routeFrom: "/"
}
passwordResetView = passwordReset { user: state.activeUser }
userView user =
userViewComponent
{ state
, setState
, user
}
components =
{ searchView
, paymentView
, paymentDetailView
, creditCardUpdateView
, passwordResetView
, userView
, needRootRedirect
}

Expand Down Expand Up @@ -201,7 +212,7 @@ render self@{ state } logger components initialHash isPersonating =
, defaultRouteElement "/fakturor" $ const components.paymentView
, routeElement true false (Just "/sök") $ const components.searchView
, simpleRoute "/#lösenord" components.passwordResetView
, defaultRouteElement "/" $ Views.userView self logger
, defaultRouteElement "/" components.userView
, defaultRouteElement "/prenumerationer/:subsno/kreditkort/uppdatera" components.creditCardUpdateView
, noMatchRoute
]
Expand Down
6 changes: 6 additions & 0 deletions apps/mitt-konto/src/MittKonto/Main/Types.purs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ type Self =
, setState :: (State -> State) -> Effect Unit
}

type UserView =
{ state :: State
, setState :: (State -> State) -> Effect Unit
, user :: User
}

setLoading :: Maybe Spinner.Loading -> State -> State
setLoading loading = _ { loading = loading }

Expand Down
238 changes: 122 additions & 116 deletions apps/mitt-konto/src/MittKonto/Main/Views/UserView.purs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module MittKonto.Main.UserView where

import Prelude

import Data.Array (snoc, sortBy, (:))
import Data.Array (all, snoc, sortBy, (:))
import Data.Maybe (Maybe(..))
import Data.String (toUpper)
import MittKonto.Main.UserView.AccountEdit as AccountEdit
Expand All @@ -11,140 +11,146 @@ import MittKonto.Main.Elements as Elements
import MittKonto.Main.Helpers as Helpers
import MittKonto.Main.Types as Types
import MittKonto.Main.UserView.Subscription (subscription) as Subscription
import MittKonto.Main.UserView.Subscription.Types (RenewSubscription)
import KSF.Api.Subscription (isSubscriptionCanceled, isSubscriptionExpired) as Subscription
import KSF.Profile.Component as Profile
import KSF.Sentry as Sentry
import KSF.User (User)
import React.Basic (JSX)
import React.Basic.DOM as DOM
import React.Basic.Hooks as React
import React.Basic.Hooks (Component, component, useState', (/\))

foreign import images :: { subscribe :: String }

-- | User info page with profile info, subscriptions, etc.
userView :: Types.Self -> Sentry.Logger -> User -> JSX
userView { state: { now, news }, setState } logger user = React.fragment
[ Helpers.classy DOM.div "col col-12 md-col-6 lg-col-6 mitt-konto--profile" [ newsView news, profileView ]
, Helpers.classy DOM.div "col col-12 md-col-6 lg-col-6" [ subscriptionsView ]
]
where
componentHeader title =
Helpers.classy DOM.span "mitt-konto--component-heading" [ DOM.text $ toUpper title ]
userView :: Sentry.Logger -> (RenewSubscription -> JSX) -> Component Types.UserView
userView logger renewSubscription = do
subscriptionComponent <- Subscription.subscription
component "UserView" \{ state: { now, news }, setState, user } -> React.do
renewingSubscription /\ setRenewingSubscription <- useState' Nothing
let componentHeader title =
Helpers.classy DOM.span "mitt-konto--component-heading" [ DOM.text $ toUpper title ]

profileView =
componentBlock
"Mina uppgifter:"
[ profileComponentBlock
, Elements.break
, editAccountBlock
, needHelp
, Elements.disappearingBreak
]
where
profileComponentBlock = componentBlockContent $ Profile.profile
{ profile: user
, onUpdate: setState <<< Types.setActiveUser <<< Just
, logger
}
editAccountBlock = DOM.div
{ className: "mitt-konto--edit-account"
, children:
[ componentHeader "Mina inställningar:"
, componentBlockContent $ AccountEdit.accountEdit
profileView =
componentBlock
"Mina uppgifter:"
[ profileComponentBlock
, Elements.break
, editAccountBlock
, needHelp
, Elements.disappearingBreak
]
}
where
profileComponentBlock = componentBlockContent "" $ Profile.profile
{ profile: user
, onUpdate: setState <<< Types.setActiveUser <<< Just
, logger
}
editAccountBlock = DOM.div
{ className: "mitt-konto--edit-account"
, children:
[ componentHeader "Mina inställningar:"
, componentBlockContent "" $ AccountEdit.accountEdit
]
}

subscriptionsView =
componentBlock "Mina prenumerationer:" $ subscriptions <> [ Elements.break, subscribeImage ]
where
subscriptions =
-- Sort the canceled subscriptions to the end of the list
case sortBy (comparing _.state) user.subs of
[] -> [ componentBlockContent noSubscriptionsText ]
subs -> do
map subscriptionComponentBlockContent subs `snoc` cancelSubscription
where
subscriptionView subscription = Subscription.subscription { subscription, user, logger, now }
subscriptionComponentBlockContent subscription
-- If the subscription has a canceled state, we want to add extra css to it.
| Subscription.isSubscriptionCanceled subscription =
DOM.div
{ className: "mitt-konto--canceled-subscription"
, children: [ componentBlockContent $ subscriptionView subscription ]
}
| Subscription.isSubscriptionExpired subscription now =
DOM.div
{ className: "mitt-konto--expired-subscription"
, children: [ componentBlockContent $ subscriptionView subscription ]
}
| otherwise = componentBlockContent $ subscriptionView subscription
subscriptionView subscription =
subscriptionComponent { subscription, user, logger, now, renewSubscription, setRenewingSubscription }

cancelSubscription =
DOM.div
{ className: "mt2"
, children:
[ IconAction.iconAction
{ iconClassName: "mitt-konto--cancel-subscription-icon"
, description: "Avsluta din prenumeration"
, onClick: IconAction.Href "https://ksfmedia1.typeform.com/to/zbh3kU"
}
]
}
subscriptionsView =
componentBlock "Mina prenumerationer:" $ subscriptions <> [ Elements.break, subscribeImage ]
where
renewing subscription = if Just subscription.subsno == renewingSubscription then " renewing" else ""
subscriptions =
-- Sort the canceled subscriptions to the end of the list
case sortBy (comparing _.state) user.subs of
[] -> [ componentBlockContent "" noSubscriptionsText ]
subs ->
(if all (\s -> Subscription.isSubscriptionCanceled s ||
Subscription.isSubscriptionExpired s now) subs
then identity else flip snoc cancelSubscription) $
map subscriptionComponentBlockContent subs
subscriptionComponentBlockContent subscription
-- If the subscription has a canceled state, we want to add extra css to it.
| Subscription.isSubscriptionCanceled subscription =
componentBlockContent (" mitt-konto--canceled-subscription" <> renewing subscription) $
subscriptionView subscription
| Subscription.isSubscriptionExpired subscription now =
componentBlockContent (" mitt-konto--expired-subscription" <> renewing subscription) $
subscriptionView subscription
| otherwise = componentBlockContent "" $ subscriptionView subscription

cancelSubscription =
DOM.div
{ className: "mt2"
, children:
[ IconAction.iconAction
{ iconClassName: "mitt-konto--cancel-subscription-icon"
, description: "Avsluta din prenumeration"
, onClick: IconAction.Href "https://ksfmedia1.typeform.com/to/zbh3kU"
}
]
}

subscribeImage =
DOM.div
{ className: "mitt-konto--subscribe-image flex"
, children:
[ Helpers.anchor "https://prenumerera.ksfmedia.fi/" "" [ DOM.img { src: images.subscribe } ] ]
}
subscribeImage =
DOM.div
{ className: "mitt-konto--subscribe-image flex"
, children:
[ Helpers.anchor "https://prenumerera.ksfmedia.fi/" "" [ DOM.img { src: images.subscribe } ] ]
}

noSubscriptionsText =
Helpers.classy DOM.div "mitt-konto--no-subscriptions"
[ DOM.p_
[ DOM.text "Har du redan en prenumeration? Kontakta vår "
, Helpers.anchor "https://www.hbl.fi/kundservice/" "kundtjänst" []
, DOM.text " och vi kopplar den till ditt konto."
noSubscriptionsText =
Helpers.classy DOM.div "mitt-konto--no-subscriptions"
[ DOM.p_
[ DOM.text "Har du redan en prenumeration? Kontakta vår "
, Helpers.anchor "https://www.hbl.fi/kundservice/" "kundtjänst" []
, DOM.text " och vi kopplar den till ditt konto."
]
]
]

needHelp :: JSX
needHelp =
DOM.div
{ className: "mitt-konto--need-help"
, children:
componentHeader "Behöver du hjälp?"
: frequentIssues
}
where
frequentIssues =
[ DOM.dl_
[ DOM.dt_ [ DOM.text "Frågor och svar" ]
, DOM.dd_ [ issueLink "HBL" "https://www.hbl.fi/fragor-och-svar/" ]
, DOM.dd_ [ issueLink "Västra Nyland" "https://www.vastranyland.fi/fragor-och-svar/" ]
, DOM.dd_ [ issueLink "Östnyland" "https://www.ostnyland.fi/fragor-och-svar/" ]
]
]
issueLink description href =
DOM.a
{ children: [ DOM.text description ]
, href
, target: "_blank"
needHelp :: JSX
needHelp =
DOM.div
{ className: "mitt-konto--need-help"
, children:
componentHeader "Behöver du hjälp?"
: frequentIssues
}
where
frequentIssues =
[ DOM.dl_
[ DOM.dt_ [ DOM.text "Frågor och svar" ]
, DOM.dd_ [ issueLink "HBL" "https://www.hbl.fi/fragor-och-svar/" ]
, DOM.dd_ [ issueLink "Västra Nyland" "https://www.vastranyland.fi/fragor-och-svar/" ]
, DOM.dd_ [ issueLink "Östnyland" "https://www.ostnyland.fi/fragor-och-svar/" ]
]
]
issueLink description href =
DOM.a
{ children: [ DOM.text description ]
, href
, target: "_blank"
}

newsView Nothing = mempty
newsView (Just n) =
componentBlock "Nyheter:" [ componentBlockContent n, Elements.break ]
newsView Nothing = mempty
newsView (Just n) =
componentBlock "Nyheter:" [ componentBlockContent "" n, Elements.break ]

componentBlock headerText content =
DOM.div
{ className: "mitt-konto--component-block-container"
, children:
componentHeader headerText
: content
}
componentBlock headerText content =
DOM.div
{ className: "mitt-konto--component-block-container"
, children:
componentHeader headerText
: content
}

componentBlockContent extraClasses child =
DOM.div
{ className: "mitt-konto--component-block-content" <> extraClasses
, children: [ child ]
}

componentBlockContent child =
DOM.div
{ className: "mitt-konto--component-block-content"
, children: [ child ]
}
pure $ React.fragment
[ Helpers.classy DOM.div "col col-12 md-col-6 lg-col-6 mitt-konto--profile" [ newsView news, profileView ]
, Helpers.classy DOM.div "col col-12 md-col-6 lg-col-6" [ subscriptionsView ]
]
Loading

0 comments on commit 442d1c3

Please sign in to comment.