coach form WIP
parent
2b0fb9e4f7
commit
6ab672ffa6
|
@ -3,7 +3,7 @@ package controllers
|
|||
import play.api.mvc._, Results._
|
||||
|
||||
import lila.app._
|
||||
import lila.coach.{ Coach => CoachModel }
|
||||
import lila.coach.{ Coach => CoachModel, CoachForm }
|
||||
import lila.user.{ User => UserModel, UserRepo }
|
||||
import views._
|
||||
|
||||
|
@ -22,4 +22,22 @@ object Coach extends LilaController {
|
|||
html.coach.show(coach)
|
||||
}
|
||||
}
|
||||
|
||||
def edit = Auth { implicit ctx =>
|
||||
me =>
|
||||
OptionOk(api find me) { c =>
|
||||
html.coach.edit(c, CoachForm edit c.coach)
|
||||
}
|
||||
}
|
||||
|
||||
def editApply = AuthBody { implicit ctx =>
|
||||
me =>
|
||||
OptionFuResult(api find me) { c =>
|
||||
implicit val req = ctx.body
|
||||
CoachForm.edit(c.coach).bindFromRequest.fold(
|
||||
form => fuccess(BadRequest(html.coach.edit(c, form))),
|
||||
data => api.update(c, data) inject Redirect(routes.Coach.show(me.username))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
@(c: lila.coach.Coach.WithUser, form: Form[_])(implicit ctx: Context)
|
||||
|
||||
@group(field: play.api.data.Field, name: Html, half: Boolean = false)(html: Html) = {
|
||||
<div class="form-group@if(half){ half}@if(field.hasErrors){ has-error}">
|
||||
@html
|
||||
<label for="@field.id" class="control-label">@name</label>
|
||||
<i class="bar"></i>
|
||||
</div>
|
||||
}
|
||||
|
||||
@moreCss = {
|
||||
@cssTag("material.form.css")
|
||||
@cssTag("coach.css")
|
||||
}
|
||||
|
||||
@layout(title = c.user.titleUsername, active = "coach",
|
||||
evenMoreCss = Some(cssTag("material.form.css"))) {
|
||||
<div class="coach_edit content_box small_box no_padding">
|
||||
<h1 class="lichess_title">
|
||||
Coach @userLink(c.user)
|
||||
</h1>
|
||||
<form class="content_box_content material form" action="@routes.Coach.edit" method="POST">
|
||||
@group(form("headline"), Html("Headline")) {
|
||||
@base.input(form("headline"))
|
||||
}
|
||||
<div class="button-container">
|
||||
<button type="submit" class="submit button text" data-icon="E">Save now</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
}
|
|
@ -1,11 +1,13 @@
|
|||
@(title: String, active: String)(body: Html)(implicit ctx: Context)
|
||||
@(title: String, active: String, evenMoreCss: Option[Html] = None)(body: Html)(implicit ctx: Context)
|
||||
|
||||
@moreCss = {
|
||||
@cssTag("coach.css")
|
||||
@evenMoreCss
|
||||
}
|
||||
|
||||
@menu = {
|
||||
<a class="@active.active("all")" href="@routes.Coach.index">All coaches</a>
|
||||
<a class="text" data-icon="" href="//lichess.org/blog/V0KrLSkAAMo3hsi4/study-chess-the-lichess-way">What are studies?</a>
|
||||
}
|
||||
|
||||
@base.layout(
|
||||
|
|
|
@ -371,6 +371,8 @@ POST /inbox/$id<\w{8}>/delete controllers.Message.delete(id: String)
|
|||
# Coach
|
||||
GET /coach controllers.Coach.index
|
||||
GET /coach/:username controllers.Coach.show(username: String)
|
||||
GET /coach/edit controllers.Coach.edit
|
||||
POST /coach/edit controllers.Coach.editApply
|
||||
|
||||
# Paste
|
||||
GET /paste controllers.Importer.importGame
|
||||
|
|
|
@ -9,7 +9,9 @@ private[coach] object BsonHandlers {
|
|||
implicit val CoachEnabledBSONHandler = booleanAnyValHandler[Coach.Enabled](_.value, Coach.Enabled.apply)
|
||||
implicit val CoachAvailableBSONHandler = booleanAnyValHandler[Coach.Available](_.value, Coach.Available.apply)
|
||||
implicit val CoachCentsBSONHandler = intAnyValHandler[Coach.Cents](_.value, Coach.Cents.apply)
|
||||
implicit val CoachMarkdownBSONHandler = stringAnyValHandler[Coach.Markdown](_.value, Coach.Markdown.apply)
|
||||
|
||||
implicit val CoachProfileMarkdownBSONHandler = stringAnyValHandler[CoachProfile.Markdown](_.value, CoachProfile.Markdown.apply)
|
||||
implicit val CoachProfileBSONHandler = Macros.handler[CoachProfile]
|
||||
|
||||
implicit val CoachBSONHandler = Macros.handler[Coach]
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@ case class Coach(
|
|||
enabledByUser: Coach.Enabled,
|
||||
enabledByMod: Coach.Enabled,
|
||||
available: Coach.Available,
|
||||
hourlyWage: Coach.Cents,
|
||||
description: Coach.Markdown,
|
||||
hourlyRate: Option[Coach.Cents],
|
||||
profile: CoachProfile,
|
||||
createdAt: DateTime,
|
||||
updatedAt: DateTime) {
|
||||
|
||||
|
@ -21,11 +21,20 @@ case class Coach(
|
|||
|
||||
object Coach {
|
||||
|
||||
def make(user: User) = Coach(
|
||||
_id = Id(user.id),
|
||||
enabledByUser = Enabled(false),
|
||||
enabledByMod = Enabled(false),
|
||||
available = Available(false),
|
||||
hourlyRate = None,
|
||||
profile = CoachProfile(),
|
||||
createdAt = DateTime.now,
|
||||
updatedAt = DateTime.now)
|
||||
|
||||
case class WithUser(coach: Coach, user: User)
|
||||
|
||||
case class Id(value: String) extends AnyVal with StringValue
|
||||
case class Enabled(value: Boolean) extends AnyVal
|
||||
case class Available(value: Boolean) extends AnyVal
|
||||
case class Cents(value: Int) extends AnyVal
|
||||
case class Markdown(value: String) extends AnyVal with StringValue
|
||||
}
|
||||
|
|
|
@ -22,6 +22,9 @@ final class CoachApi(coll: Coll) {
|
|||
}
|
||||
}
|
||||
|
||||
def update(c: Coach.WithUser, data: CoachForm.Data): Funit =
|
||||
coll.update($id(c.coach.id), data(c.coach)).void
|
||||
|
||||
private def withUser(user: User)(coach: Coach): Coach.WithUser =
|
||||
Coach.WithUser(coach, user)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package lila.coach
|
||||
|
||||
import org.joda.time.DateTime
|
||||
import play.api.data._
|
||||
import play.api.data.format.Formatter
|
||||
import play.api.data.Forms._
|
||||
|
||||
object CoachForm {
|
||||
|
||||
def edit(coach: Coach) = Form(mapping(
|
||||
"hourlyRate" -> optional(number(min = 5, max = 500)),
|
||||
"available" -> optional(number),
|
||||
"profile" -> profileMapping
|
||||
)(Data.apply)(Data.unapply)) fill Data(
|
||||
hourlyRate = coach.hourlyRate.map(_.value),
|
||||
available = coach.available.value option 1,
|
||||
profile = coach.profile)
|
||||
|
||||
case class Data(
|
||||
hourlyRate: Option[Int],
|
||||
available: Option[Int],
|
||||
profile: CoachProfile) {
|
||||
|
||||
def apply(coach: Coach) = coach.copy(
|
||||
hourlyRate = hourlyRate.map(_ * 100) map Coach.Cents.apply,
|
||||
available = Coach.Available(available.isDefined),
|
||||
profile = profile,
|
||||
updatedAt = DateTime.now)
|
||||
}
|
||||
|
||||
private def profileMapping = mapping(
|
||||
"headline" -> optional(nonEmptyText(minLength = 5, maxLength = 140)),
|
||||
"description" -> optional(markdown),
|
||||
"playingExperience" -> optional(markdown),
|
||||
"teachingExperience" -> optional(markdown),
|
||||
"otherExperience" -> optional(markdown),
|
||||
"skills" -> optional(markdown),
|
||||
"methodology" -> optional(markdown)
|
||||
)(CoachProfile.apply)(CoachProfile.unapply)
|
||||
|
||||
import CoachProfile.Markdown
|
||||
|
||||
private def markdown = of[Markdown]
|
||||
private implicit def markdownFormat: Formatter[Markdown] = new Formatter[Markdown] {
|
||||
def bind(key: String, data: Map[String, String]) =
|
||||
data.get(key).map(Markdown.apply).toRight(Seq(FormError(key, "error.required", Nil)))
|
||||
def unbind(key: String, value: Markdown) = Map(key -> value.value)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package lila.coach
|
||||
|
||||
case class CoachProfile(
|
||||
headline: Option[String] = None,
|
||||
description: Option[CoachProfile.Markdown] = None,
|
||||
playingExperience: Option[CoachProfile.Markdown] = None,
|
||||
teachingExperience: Option[CoachProfile.Markdown] = None,
|
||||
otherExperience: Option[CoachProfile.Markdown] = None,
|
||||
skills: Option[CoachProfile.Markdown] = None,
|
||||
methodology: Option[CoachProfile.Markdown] = None)
|
||||
|
||||
object CoachProfile {
|
||||
|
||||
case class Markdown(value: String) extends AnyVal with StringValue
|
||||
}
|
Loading…
Reference in New Issue