Tweetbox with Mithril and Redux

HTML

<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/redux/3.0.4/redux.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/mithril/0.2.1/mithril.min.js"></script>
<div class="container-fluid" id="main">
  <div class="row">
    <div class="col-xs-12 col-md-4">
      <div id="app"></div>
    </div>
  </div>
</div>

CSS

#main {
  margin-top: 20px;
}

CoffeeScript

initialState = 
  text: ""
  photoAdded: false

replace = (x, v) ->
  Object.assign {}, x, v
  
vm = (state, action) ->
  if state is undefined then return initialState
  switch action.type
    when "CHANGE_TEXT" then Object.assign {}, state, {text: action.text}
    when "TOGGLE_PHOTO" then replace state, {photoAdded: !state.photoAdded}

computeProps = (state) ->
  {state 
    ,disableBtn: state.text is ""
    remainingChars: 140 - state.text.length - 23*state.photoAdded
    photoBtnText: if state.photoAdded then 'Photo Added' else 'Add Photo'
  }
  

TweetBox = {}
TweetBox.controller = (props) ->
  handleInput: (e) => 
    props.dispatch type: "CHANGE_TEXT", text: e.target.value
  togglePhoto: (e) => 
    props.dispatch type: "TOGGLE_PHOTO"

TweetBox.view = (ctrl, props) ->
  console.log(props)
  vm = computeProps(props.getState())
  m '.clearfix',
    m 'h4', 'TweetBox with Mithril'
    m '.well',
      m 'textarea.form-control', 
        style: 
          "margin-bottom": "20px"
          resize: "vertical"
        oninput: ctrl.handleInput
      m '.pull-right',
        m 'button.btn.btn-default.btn-sm',
          onclick: ctrl.togglePhoto
        , vm.photoBtnText
        m 'button.btn.btn-primary.btn-sm', 
          disabled: vm.disableBtn
        , 'Tweet'
      m 'span.remaining', vm.remainingChars
      
    
ReduxMithrilWrapper = (component, model) -> 
  store = Redux.createStore(model)
  render = ->
    m.render document.getElementById("app"), m(component, store)
  store.subscribe(render)
  render()
  
ReduxMithrilWrapper(TweetBox, vm)