coach integration and settings UI
parent
0b49aa6657
commit
fa9d5ecba3
|
@ -18,7 +18,6 @@ object layout {
|
|||
evenMoreJs: Html = emptyHtml
|
||||
)(body: Html)(implicit ctx: Context) = views.html.base.layout(
|
||||
title = title,
|
||||
menu = Some(frag()),
|
||||
moreCss = frag(responsiveCssTag("account"), evenMoreCss),
|
||||
responsive = true,
|
||||
moreJs = frag(jsTag("account.js"), evenMoreJs)
|
||||
|
@ -37,7 +36,7 @@ object layout {
|
|||
a(cls := active.activeO("editProfile"), href := routes.Account.profile())(
|
||||
trans.editProfile.frag()
|
||||
),
|
||||
isGranted(_.Coach) option a(href := routes.Coach.edit)("Coach profile"),
|
||||
isGranted(_.Coach) option a(cls := active.activeO("coach"), href := routes.Coach.edit)("Coach profile"),
|
||||
div(cls := "sep"),
|
||||
a(cls := active.activeO("password"), href := routes.Account.passwd())(
|
||||
trans.changePassword.frag()
|
||||
|
|
|
@ -7,102 +7,101 @@
|
|||
@jsTag("coach.form.js")
|
||||
}
|
||||
|
||||
@base.layout(title = s"${c.user.titleUsername} coach page",
|
||||
moreCss = responsiveCssTag("coach.editor"),
|
||||
responsive = true,
|
||||
moreJs = moreJs) {
|
||||
<main class="coach-edit">
|
||||
<aside class="coach-side">
|
||||
<a href="@routes.Coach.show(c.user.username)" class="button button-empty text" data-icon="v">Preview coach page</a>
|
||||
</aside>
|
||||
<div class="coach-main box">
|
||||
<div class="top">
|
||||
<div class="picture_wrap">
|
||||
@if(c.coach.hasPicture) {
|
||||
<a class="upload_picture" href="@routes.Coach.picture" title="Change/delete your profile picture">
|
||||
@widget.pic(c, 250).toHtml
|
||||
</a>
|
||||
} else {
|
||||
<div class="upload_picture">
|
||||
<a class="button" href="@routes.Coach.picture">Upload a profile picture</a>
|
||||
@account.layout(
|
||||
title = s"${c.user.titleUsername} coach page",
|
||||
evenMoreCss = responsiveCssTag("coach.editor"),
|
||||
evenMoreJs = moreJs,
|
||||
active = "coach") {
|
||||
<div class="account coach-edit box">
|
||||
<div class="top">
|
||||
<div class="picture_wrap">
|
||||
@if(c.coach.hasPicture) {
|
||||
<a class="upload_picture" href="@routes.Coach.picture" title="Change/delete your profile picture">
|
||||
@widget.pic(c, 250).toHtml
|
||||
</a>
|
||||
} else {
|
||||
<div class="upload_picture">
|
||||
<a class="button" href="@routes.Coach.picture">Upload a profile picture</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="overview">
|
||||
<h1>@widget.titleName(c).toHtml</h1>
|
||||
<div class="todo" data-profile="@c.user.profileOrDefault.isComplete">
|
||||
<h3>TODO list before publishing your coach profile</h3>
|
||||
<ul></ul>
|
||||
</div>
|
||||
<div>
|
||||
<a href="@routes.Coach.show(c.user.username)" class="button button-empty text" data-icon="v">Preview coach page</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="box__pad form3" action="@routes.Coach.edit" method="POST">
|
||||
<div class="tabs">
|
||||
<div data-tab="basics" class="active">Basics</div>
|
||||
<div data-tab="texts">Texts</div>
|
||||
<div data-tab="contents">Contents</div>
|
||||
<div data-tab="reviews" data-count="@reviews.list.size" class="data-count">
|
||||
Pending reviews
|
||||
</div>
|
||||
</div>
|
||||
<div class="panels">
|
||||
<div class="panel basics active">
|
||||
@form3.split {
|
||||
@form3.checkbox(form("listed"), raw("Publish on the coaches list"), help = raw("Enable when your profile is ready").some, half = true)
|
||||
@form3.checkbox(form("available"), raw("Currently available for lessons"), help = raw("Enable to get more students").some, half = true)
|
||||
}
|
||||
@form3.group(form("profile.headline"), raw("Short and inspiring headline"), help = raw("Just one sentence to make students want to choose you").some)(form3.input(_))
|
||||
@form3.split {
|
||||
@form3.group(form("profile.languages"), raw("Languages spoken"), help = raw("Which languages can you give lessons in?").some, half = true)(form3.input(_))
|
||||
@form3.group(form("profile.hourlyRate"), raw("Hourly rate"), help = raw("Indicative, non-contractual").some, half = true)(form3.input(_))
|
||||
}
|
||||
</div>
|
||||
<div class="panel texts">
|
||||
@form3.group(form("profile.description"), raw("Who are you?"), help = raw("Age, profession, country... let your students know you").some)(form3.textarea(_)(*.rows := 8))
|
||||
@form3.group(form("profile.playingExperience"), raw("Playing experience"), help = raw("Tournaments played, best wins, other achievements").some)(form3.textarea(_)(*.rows := 8))
|
||||
@form3.group(form("profile.teachingExperience"), raw("Teaching experience"), help = raw("Diplomas, years of practice, best student results").some)(form3.textarea(_)(*.rows := 8))
|
||||
@form3.group(form("profile.otherExperience"), raw("Other experiences"), help = raw("E.g. as chess commentator, or teaching other domains").some)(form3.textarea(_)(*.rows := 8))
|
||||
@form3.group(form("profile.skills"), raw("Best skills in chess and teaching"))(form3.textarea(_)(*.rows := 8))
|
||||
@form3.group(form("profile.methodology"), raw("Teaching methodology"), help = raw("How you prepare and run lessons. How you follow up with students.").some)(form3.textarea(_)(*.rows := 8))
|
||||
</div>
|
||||
<div class="panel contents">
|
||||
@form3.group(form("profile.publicStudies"), raw("Featured public lichess studies"), help = raw("Up to 6 lichess study URLs, one per line").some)(form3.textarea(_)())
|
||||
@form3.group(form("profile.youtubeChannel"), raw("URL of your Youtube channel"))(form3.input(_))
|
||||
|
||||
@form3.group(form("profile.youtubeVideos"), raw("Featured youtube videos"), help = raw("Up to 6 Youtube video URLs, one per line").some)(form3.textarea(_)(*.rows := 6))
|
||||
</div>
|
||||
<div class="panel reviews">
|
||||
<p class="help text" data-icon="">Reviews are visible only after you approve them.</p>
|
||||
@reviews.list.map { r =>
|
||||
<div class="review" data-action="@routes.Coach.approveReview(r.id)">
|
||||
<div class="user">
|
||||
@userIdLink(r.userId.some)
|
||||
review.barRating(selected = r.score.some, enabled = false).toHtml
|
||||
@momentFromNow(r.updatedAt)
|
||||
</div>
|
||||
<div class="content">
|
||||
@if(r.moddedAt.isDefined) {
|
||||
<div class="modded">
|
||||
Moderators have disapproved this review. Please only accept reviews from
|
||||
actual students, based on actual lessons. Reviews must be about your coaching services.
|
||||
<br />
|
||||
You may delete this review, or ask the author to rephrase it, then approve it.
|
||||
</div>
|
||||
}
|
||||
@richText(r.text)
|
||||
</div>
|
||||
<div class="actions">
|
||||
@if(r.moddedAt.fold(true)(_.isBefore(r.updatedAt))) {
|
||||
<a data-value="1" class="yes" data-icon="E"></a>
|
||||
}
|
||||
<a data-value="0" class="no" data-icon="L"></a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="overview">
|
||||
<h1>@widget.titleName(c).toHtml</h1>
|
||||
<div class="todo" data-profile="@c.user.profileOrDefault.isComplete">
|
||||
<h3>TODO list before publishing your coach profile</h3>
|
||||
<ul></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="box__pad form3" action="@routes.Coach.edit" method="POST">
|
||||
<div class="tabs">
|
||||
<div data-tab="basics" class="active">Basics</div>
|
||||
<div data-tab="texts">Texts</div>
|
||||
<div data-tab="contents">Contents</div>
|
||||
<div data-tab="reviews" data-count="@reviews.list.size" class="data-count">
|
||||
Pending reviews
|
||||
</div>
|
||||
</div>
|
||||
<div class="panels">
|
||||
<div class="panel basics active">
|
||||
@form3.split {
|
||||
@form3.checkbox(form("listed"), raw("Publish on the coaches list"), help = raw("Enable when your profile is ready").some, half = true)
|
||||
@form3.checkbox(form("available"), raw("Currently available for lessons"), help = raw("Enable to get more students").some, half = true)
|
||||
}
|
||||
@form3.group(form("profile.headline"), raw("Short and inspiring headline"), help = raw("Just one sentence to make students want to choose you").some)(form3.input(_))
|
||||
@form3.split {
|
||||
@form3.group(form("profile.languages"), raw("Languages spoken"), help = raw("Which languages can you give lessons in?").some, half = true)(form3.input(_))
|
||||
@form3.group(form("profile.hourlyRate"), raw("Hourly rate"), help = raw("Indicative, non-contractual").some, half = true)(form3.input(_))
|
||||
}
|
||||
</div>
|
||||
<div class="panel texts">
|
||||
@form3.group(form("profile.description"), raw("Who are you?"), help = raw("Age, profession, country... let your students know you").some)(form3.textarea(_)(*.rows := 8))
|
||||
@form3.group(form("profile.playingExperience"), raw("Playing experience"), help = raw("Tournaments played, best wins, other achievements").some)(form3.textarea(_)(*.rows := 8))
|
||||
@form3.group(form("profile.teachingExperience"), raw("Teaching experience"), help = raw("Diplomas, years of practice, best student results").some)(form3.textarea(_)(*.rows := 8))
|
||||
@form3.group(form("profile.otherExperience"), raw("Other experiences"), help = raw("E.g. as chess commentator, or teaching other domains").some)(form3.textarea(_)(*.rows := 8))
|
||||
@form3.group(form("profile.skills"), raw("Best skills in chess and teaching"))(form3.textarea(_)(*.rows := 8))
|
||||
@form3.group(form("profile.methodology"), raw("Teaching methodology"), help = raw("How you prepare and run lessons. How you follow up with students.").some)(form3.textarea(_)(*.rows := 8))
|
||||
</div>
|
||||
<div class="panel contents">
|
||||
@form3.group(form("profile.publicStudies"), raw("Featured public lichess studies"), help = raw("Up to 6 lichess study URLs, one per line").some)(form3.textarea(_)())
|
||||
@form3.group(form("profile.youtubeChannel"), raw("URL of your Youtube channel"))(form3.input(_))
|
||||
|
||||
@form3.group(form("profile.youtubeVideos"), raw("Featured youtube videos"), help = raw("Up to 6 Youtube video URLs, one per line").some)(form3.textarea(_)(*.rows := 6))
|
||||
</div>
|
||||
<div class="panel reviews">
|
||||
<p class="help text" data-icon="">Reviews are visible only after you approve them.</p>
|
||||
@reviews.list.map { r =>
|
||||
<div class="review" data-action="@routes.Coach.approveReview(r.id)">
|
||||
<div class="user">
|
||||
@userIdLink(r.userId.some)
|
||||
review.barRating(selected = r.score.some, enabled = false).toHtml
|
||||
@momentFromNow(r.updatedAt)
|
||||
</div>
|
||||
<div class="content">
|
||||
@if(r.moddedAt.isDefined) {
|
||||
<div class="modded">
|
||||
Moderators have disapproved this review. Please only accept reviews from
|
||||
actual students, based on actual lessons. Reviews must be about your coaching services.
|
||||
<br />
|
||||
You may delete this review, or ask the author to rephrase it, then approve it.
|
||||
</div>
|
||||
}
|
||||
@richText(r.text)
|
||||
</div>
|
||||
<div class="actions">
|
||||
@if(r.moddedAt.fold(true)(_.isBefore(r.updatedAt))) {
|
||||
<a data-value="1" class="yes" data-icon="E"></a>
|
||||
}
|
||||
<a data-value="0" class="no" data-icon="L"></a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="status text" data-icon="E">Your changes have been saved.</div>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
<div class="status text" data-icon="E">Your changes have been saved.</div>
|
||||
</form>
|
||||
</div>
|
||||
}.toHtml
|
||||
|
|
|
@ -17,7 +17,7 @@ object index {
|
|||
responsive = true,
|
||||
moreJs = infiniteScrollTag
|
||||
) {
|
||||
main(cls := "coach-list")(
|
||||
main(cls := "coach-list coach-full-page")(
|
||||
st.aside(cls := "coach-list__side coach-side")(
|
||||
img(src := staticUrl("images/icons/certification.svg"), cls := "coach-list__certification"),
|
||||
h1("Certified coaches"),
|
||||
|
|
|
@ -10,37 +10,32 @@ import controllers.routes
|
|||
object picture {
|
||||
|
||||
def apply(c: lila.coach.Coach.WithUser, error: Option[String] = None)(implicit ctx: Context) =
|
||||
views.html.base.layout(
|
||||
views.html.account.layout(
|
||||
title = s"${c.user.titleUsername} coach picture",
|
||||
moreJs = jsTag("coach.form.js"),
|
||||
moreCss = responsiveCssTag("coach.editor"),
|
||||
responsive = true
|
||||
evenMoreJs = jsTag("coach.form.js"),
|
||||
evenMoreCss = responsiveCssTag("coach.editor"),
|
||||
active = "coach"
|
||||
) {
|
||||
main(cls := "coach-picture")(
|
||||
st.aside(cls := "coach-side")(
|
||||
a(href := routes.Coach.edit, cls := "text", dataIcon := "I")("Return to coach page form")
|
||||
),
|
||||
div(cls := "coach-main box")(
|
||||
div(cls := "top")(
|
||||
div(cls := "picture_wrap")(
|
||||
widget.pic(c, 250)
|
||||
),
|
||||
h1(widget.titleName(c))
|
||||
div(cls := "account coach-edit coach-picture box")(
|
||||
div(cls := "top")(
|
||||
div(cls := "picture_wrap")(
|
||||
widget.pic(c, 250)
|
||||
),
|
||||
div(cls := "forms")(
|
||||
error.map { e =>
|
||||
p(cls := "error")(e)
|
||||
},
|
||||
st.form(action := routes.Coach.pictureApply, enctype := "multipart/form-data", cls := "upload")(
|
||||
p("Max size: ", lila.db.Photographer.uploadMaxMb, "MB."),
|
||||
form3.file.image("picture"),
|
||||
button(tpe := "submit", cls := "button")("Upload profile picture")
|
||||
),
|
||||
c.coach.hasPicture option
|
||||
st.form(action := routes.Coach.pictureDelete, cls := "delete")(
|
||||
button(tpe := "submit", cls := "confirm button button-empty button-red")("Delete profile picture")
|
||||
)
|
||||
)
|
||||
h1(widget.titleName(c))
|
||||
),
|
||||
div(cls := "forms")(
|
||||
error.map { e =>
|
||||
p(cls := "error")(e)
|
||||
},
|
||||
st.form(action := routes.Coach.pictureApply, enctype := "multipart/form-data", cls := "upload")(
|
||||
p("Max size: ", lila.db.Photographer.uploadMaxMb, "MB."),
|
||||
form3.file.image("picture"),
|
||||
button(tpe := "submit", cls := "button")("Upload profile picture")
|
||||
),
|
||||
c.coach.hasPicture option
|
||||
st.form(action := routes.Coach.pictureDelete, cls := "delete")(
|
||||
button(tpe := "submit", cls := "confirm button button-empty button-red")("Delete profile picture")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ $('.coach-review-form form').show();
|
|||
image = c.coach.picturePath.map(p => dbImageUrl(p.value))
|
||||
).some
|
||||
) {
|
||||
main(cls := "coach-show")(
|
||||
main(cls := "coach-show coach-full-page")(
|
||||
st.aside(cls := "coach-show__side coach-side")(
|
||||
a(cls := "button button-empty", href := routes.User.show(c.user.username))("View ", c.user.username, " lichess profile"),
|
||||
if (ctx.me.exists(c.coach.is)) frag(
|
||||
|
|
|
@ -15,7 +15,6 @@ group.radio {
|
|||
justify-content: center;
|
||||
padding: 10px;
|
||||
height: 100%;
|
||||
line-height: 1.8em;
|
||||
cursor:pointer;
|
||||
border-right: $border;
|
||||
user-select: none;
|
||||
|
|
|
@ -85,13 +85,10 @@
|
|||
}
|
||||
& form section {
|
||||
margin-bottom: 4rem;
|
||||
& label {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
}
|
||||
& h2 {
|
||||
margin-bottom: 1.5rem;
|
||||
font-size: 1.5em;
|
||||
margin-bottom: 1.3rem;
|
||||
font-size: 1.3em;
|
||||
@include breakpoint($mq-x-small) {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
|
|
@ -5,15 +5,15 @@
|
|||
.coach-picture {
|
||||
& .top {
|
||||
display: flex;
|
||||
line-height: 2;
|
||||
}
|
||||
& .top h1 {
|
||||
@extend %roboto;
|
||||
margin: 0;
|
||||
padding: 0!important;
|
||||
font-size: 32px;
|
||||
font-size: 2rem;
|
||||
line-height: 2;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 4px;
|
||||
letter-spacing: 3px;
|
||||
}
|
||||
|
||||
& .top .picture_wrap {
|
||||
|
@ -37,12 +37,16 @@
|
|||
flex-flow: column;
|
||||
}
|
||||
|
||||
& .overview .todo,
|
||||
& .overview.with_todo .analytics {
|
||||
& .overview .todo {
|
||||
display: none;
|
||||
}
|
||||
& .overview.with_todo .todo {
|
||||
display: block;
|
||||
@extend %box-radius;
|
||||
border-radius: 20px;
|
||||
padding: 1rem;
|
||||
background: mix($c-error, $c-bg-box, 15%);
|
||||
border: 1px solid $c-error;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
& .overview .todo h3 {
|
||||
margin: 0;
|
||||
|
|
|
@ -1,26 +1,31 @@
|
|||
$mq-coach-col2: $mq-medium;
|
||||
|
||||
main {
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
'main'
|
||||
'side';
|
||||
|
||||
& .coach-main {
|
||||
grid-area: main;
|
||||
}
|
||||
& .coach-side {
|
||||
grid-area: side;
|
||||
margin: 2em 2em 0 2em;
|
||||
}
|
||||
|
||||
@include breakpoint($mq-coach-col2) {
|
||||
grid-template-columns: 300px auto;
|
||||
grid-template-areas:
|
||||
'side main';
|
||||
grid-gap: 2rem;
|
||||
&.coach-full-page {
|
||||
|
||||
& .coach-side {
|
||||
margin: 4rem 0 0 0;
|
||||
grid-area: side;
|
||||
margin: 2em 2em 0 2em;
|
||||
}
|
||||
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
'main'
|
||||
'side';
|
||||
|
||||
@include breakpoint($mq-coach-col2) {
|
||||
grid-template-columns: 300px auto;
|
||||
grid-template-areas:
|
||||
'side main';
|
||||
grid-gap: 2rem;
|
||||
& .coach-side {
|
||||
margin: 4rem 0 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,8 +43,8 @@
|
|||
margin-bottom: 3rem;
|
||||
}
|
||||
&.erased {
|
||||
background: rgba(128,128,128,0.2);
|
||||
opacity: 0.5;
|
||||
background: $c-shade;
|
||||
opacity: 0.6;
|
||||
}
|
||||
&.erased .forum-post__message {
|
||||
font-style: italic;
|
||||
|
|
Loading…
Reference in New Issue