Last active
August 29, 2015 14:18
-
-
Save cschneid/71d397f6decf9b78e589 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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