Skip to content

Instantly share code, notes, and snippets.

@cschneid
Last active August 29, 2015 14:18
Show Gist options
  • Save cschneid/71d397f6decf9b78e589 to your computer and use it in GitHub Desktop.
Save cschneid/71d397f6decf9b78e589 to your computer and use it in GitHub Desktop.
module MealPlan where
import Network.Http.StatusHelpers
import qualified Grocery.Types as GT
import Grocery.ListHelpers
import Utils.Actions
import Types
import qualified Login.StateMachine as Login
import qualified Calendar.View
import Login.Action
import Control.Concurrent
import Prelude hiding (div)
import Blaze.Core
import Blaze.ReactJS.Base
import qualified Blaze.ReactJS.Run as ReactJS
import qualified Text.Blaze.Event as E
import qualified Text.Blaze.Event.Keycode as Keycode
import qualified Text.Blaze.Html5 as H
import qualified Text.Blaze.Html5.Attributes as A
import Control.Monad.State
import Control.Monad.Writer
import Control.Lens
import qualified Data.Text as T
import Data.Maybe
import Data.Typeable
import Data.Foldable (foldMap)
import Data.Time
import Data.List
import System.Locale (defaultTimeLocale)
------------------------------------------------------------------------------
-- Rendering
------------------------------------------------------------------------------
renderState :: MealPlanState -> WindowState MealPlanAction
renderState state = WindowState
{ _wsBody = renderBody state
, _wsPath = ""
}
renderBody :: MealPlanState -> H.Html MealPlanAction
renderBody st = do
H.div $ H.toHtml $ show st
H.div $ H.toHtml $ st ^. flashMessage
case st ^. uiState of
LoginScreen -> renderLoginForm st
RegisterScreen -> renderRegisterForm st
CalendarScreen -> renderMealPlanCalendar st
renderLoginForm :: MealPlanState -> H.Html MealPlanAction
renderLoginForm st = do
let email = st ^. user . GT.userEmail
let (GT.UnhashedPassword pass) = st ^. user . GT.userPassword
case st ^. loginState of
Login.LoggedIn u -> do
H.div $ do
"Logged in as: "
H.toHtml (u ^. GT.userEmail)
H.button H.! E.onClick' LogoutUserA $ "Logout!"
Login.LoggedOut message -> do
when (isJust message) $
H.div $ (H.toHtml . fromJust) message
H.input H.! A.id "userEmail"
H.! A.placeholder "Email:"
H.! A.value (H.toValue email)
H.! E.onValueChange UpdateUsernameA
H.input H.! A.id "userPassword"
H.! A.type_ "password"
H.! A.placeholder "Password:"
H.! A.value (H.toValue pass)
H.! E.onValueChange UpdateUserPasswordA
H.button H.! E.onClick' LoginUserA $ "Login!"
Login.LoginInProgress{} -> H.div "Logging In..."
H.button H.! E.onClick' RegisterUserA $ "Register!"
renderRegisterForm :: MealPlanState -> H.Html MealPlanAction
renderRegisterForm st = do
H.h1 "Register!"
H.button H.! E.onClick' (ChangeToScreenA LoginScreen) $ "Already have an account? Login!"
renderMealPlanCalendar :: MealPlanState -> H.Html MealPlanAction
renderMealPlanCalendar st = do
H.h1 "Meal Plan"
foldMap (\oneDay -> do
let formattedDay = formatDay $ (head oneDay) ^. GT.day
H.h2 $ H.toHtml $ formattedDay
foldMap Calendar.View.renderMeal oneDay) (mealsPerDay $ st ^. meals)
where formatDay = formatTime defaultTimeLocale "%a, %b %d"
mealsPerDay = groupBy (\a b -> a ^. GT.day == b ^. GT.day)
------------------------------------------------------------------------------
-- Handling
------------------------------------------------------------------------------
applyMealPlanAction :: MealPlanAction -> ApplyActionM MealPlanState MealPlanRequest ()
applyMealPlanAction action =
case action of
UpdateUsernameA e -> user . GT.userEmail .= e
UpdateUserPasswordA p -> user . GT.userPassword .= GT.UnhashedPassword p
LoginUserA -> do
u <- use user
tell [loginUser u]
RegisterUserA -> do
u <- use user
tell [registerUser u]
LogoutUserA -> tell [logoutUser]
LoginResultA laction -> do
newState <- loginState <%= (Login.transition laction)
case newState of
Login.LoggedIn{} -> uiState .= CalendarScreen
_ -> uiState .= LoginScreen
ChangeToScreenA s -> uiState .= s
UpdateFlashA t -> flashMessage .= t
NullActionA -> return ()
------------------------------------------------------------------------------
-- App
------------------------------------------------------------------------------
app :: App MealPlanState MealPlanAction MealPlanRequest
app = App
{ appInitialState = initialState
, appInitialRequest = []
, appApplyAction = runApplyActionM . applyMealPlanAction
}
initialState :: MealPlanState
initialState =
MealPlanState {
_uiState = LoginScreen
, _user = GT.emptyUser
, _loginState = (Login.LoggedOut Nothing)
, _flashMessage = ""
, _meals = dummyMealPlan
}
dummyMealPlan :: [GT.Meal]
dummyMealPlan = [
GT.Meal (fromGregorian 2015 4 8) "Breakfast" [GT.Recipe "Cowboy Breakfast" [GT.Food "Hamburger", GT.Food "Gravy"] ]
, GT.Meal (fromGregorian 2015 4 8) "Lunch" [GT.Recipe "Cookie" [GT.Food "Cookie"] ]
, GT.Meal (fromGregorian 2015 4 9) "Breakfast" [GT.Recipe "Cowboy Breakfast" [GT.Food "Hamburger", GT.Food "Gravy"] ]
, GT.Meal (fromGregorian 2015 4 9) "Lunch" [GT.Recipe "Cookie" [GT.Food "Cookie"] ]
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment