From 16699b0654a1a81ec6fcc3f826b41c1941e634a4 Mon Sep 17 00:00:00 2001 From: Ashar Fuadi Date: Sat, 16 Sep 2023 11:34:42 +0700 Subject: [PATCH] feat(client): more responsive layout in mobile (#513) --- .../CourseChaptersSidebar.jsx | 71 +++++++++++++++---- .../CourseChaptersSidebar.scss | 36 ++++++++-- .../courses/single/SingleCourseRoutes.scss | 1 + .../ChapterProblemPage/ChapterProblemPage.jsx | 3 + .../ChapterProblemCard.scss | 8 ++- 5 files changed, 100 insertions(+), 19 deletions(-) diff --git a/judgels-client/src/routes/courses/courses/single/CourseChaptersSidebar/CourseChaptersSidebar.jsx b/judgels-client/src/routes/courses/courses/single/CourseChaptersSidebar/CourseChaptersSidebar.jsx index 8c15653a3..4ceee4492 100644 --- a/judgels-client/src/routes/courses/courses/single/CourseChaptersSidebar/CourseChaptersSidebar.jsx +++ b/judgels-client/src/routes/courses/courses/single/CourseChaptersSidebar/CourseChaptersSidebar.jsx @@ -1,3 +1,5 @@ +import { Popover, Position } from '@blueprintjs/core'; +import { ChevronDown, ChevronRight, Menu } from '@blueprintjs/icons'; import classNames from 'classnames'; import { Component } from 'react'; import { connect } from 'react-redux'; @@ -15,6 +17,7 @@ import './CourseChaptersSidebar.scss'; class CourseChaptersSidebar extends Component { state = { response: undefined, + isResponsivePopoverOpen: false, }; async componentDidMount() { @@ -22,19 +25,43 @@ class CourseChaptersSidebar extends Component { this.setState({ response }); } + componentDidUpdate() {} + render() { return ( -
- {this.renderChapters()} -
+ <> +
+ {this.renderChapters({ showName: !this.isInProblemPath() })} +
+ +
+ +

+

+  Chapters Menu +

+ +
+ ); } - renderChapters = () => { + renderChapters = ({ showName }) => { const { course, match, onPutCourseChapter } = this.props; const { response } = this.state; if (!course || !response) { @@ -49,18 +76,22 @@ class CourseChaptersSidebar extends Component { 'course-chapters-sidebar__item--selected': this.isInChapterPath(courseChapter.alias), })} to={`${match.url}/chapters/${courseChapter.alias}`} - onClick={() => + onClick={() => { onPutCourseChapter({ jid: courseChapter.chapterJid, name: chaptersMap[courseChapter.chapterJid].name, alias: courseChapter.alias, courseSlug: course.slug, - }) - } + }); + + if (this.state.isResponsivePopoverOpen) { + this.onResponsiveItemClick(); + } + }} >
- {courseChapter.alias} {!this.isInProblemPath() && <>. {chaptersMap[courseChapter.chapterJid].name}} -   + {courseChapter.alias} {showName && <>. {chaptersMap[courseChapter.chapterJid].name}} +    {this.renderProgress(chapterProgressesMap[courseChapter.chapterJid])}
{!this.isInProblemPath() && this.renderProgressBar(chapterProgressesMap[courseChapter.chapterJid])} @@ -68,6 +99,10 @@ class CourseChaptersSidebar extends Component { )); }; + isInChaptersPath = () => { + return this.props.location.pathname.includes('/chapters/'); + }; + isInChapterPath = chapterAlias => { return (this.props.location.pathname + '/') .replace('//', '/') @@ -97,6 +132,16 @@ class CourseChaptersSidebar extends Component { } return ; }; + + onResponsivePopoverInteraction = state => { + this.setState({ isResponsivePopoverOpen: state }); + }; + + onResponsiveItemClick = () => { + setTimeout(() => { + this.setState({ isResponsivePopoverOpen: false }); + }, 200); + }; } const mapStateToProps = state => ({ diff --git a/judgels-client/src/routes/courses/courses/single/CourseChaptersSidebar/CourseChaptersSidebar.scss b/judgels-client/src/routes/courses/courses/single/CourseChaptersSidebar/CourseChaptersSidebar.scss index e494c0281..68d9e1b2f 100644 --- a/judgels-client/src/routes/courses/courses/single/CourseChaptersSidebar/CourseChaptersSidebar.scss +++ b/judgels-client/src/routes/courses/courses/single/CourseChaptersSidebar/CourseChaptersSidebar.scss @@ -8,8 +8,7 @@ font-family: $accent-font; background-color: inherit !important; box-shadow: none !important; - - transition: all 0.2s ease-in-out; + transition: flex-grow 0.2s ease-in-out; hr { margin: 0 !important; @@ -19,6 +18,10 @@ flex-grow: unset; margin-right: 10px; } + + &__responsive { + display: none; + } } a.course-chapters-sidebar__item { @@ -73,7 +76,32 @@ a.course-chapters-sidebar__item { @media only screen and (max-width: 750px) { .course-chapters-sidebar { - flex-grow: unset; - margin-right: 10px; + &__full { + display: none; + } + + &__responsive { + display: block; + flex: none; + width: 100%; + max-width: unset; + margin-top: 0; + margin-bottom: 10px; + } + } +} + +@media only screen and (max-width: 1024px) { + .course-chapters-sidebar--wide.course-chapters-sidebar__full { + display: block; + flex: none; + order: 2; + width: 100%; + max-width: unset; + margin-top: 20px; + } + + .course-chapters-sidebar--wide.course-chapters-sidebar__responsive { + display: none; } } diff --git a/judgels-client/src/routes/courses/courses/single/SingleCourseRoutes.scss b/judgels-client/src/routes/courses/courses/single/SingleCourseRoutes.scss index f2835bbd4..b791714f8 100644 --- a/judgels-client/src/routes/courses/courses/single/SingleCourseRoutes.scss +++ b/judgels-client/src/routes/courses/courses/single/SingleCourseRoutes.scss @@ -1,4 +1,5 @@ .single-course-routes { display: flex; + flex-wrap: wrap; width: 100%; } diff --git a/judgels-client/src/routes/courses/courses/single/chapters/single/problems/single/ChapterProblemPage/ChapterProblemPage.jsx b/judgels-client/src/routes/courses/courses/single/chapters/single/problems/single/ChapterProblemPage/ChapterProblemPage.jsx index 00499944a..4f286029c 100644 --- a/judgels-client/src/routes/courses/courses/single/chapters/single/problems/single/ChapterProblemPage/ChapterProblemPage.jsx +++ b/judgels-client/src/routes/courses/courses/single/chapters/single/problems/single/ChapterProblemPage/ChapterProblemPage.jsx @@ -100,6 +100,9 @@ export class ChapterProblemPage extends Component { } const { progress } = response; + if (!progress) { + return null; + } return ; }; diff --git a/judgels-client/src/routes/courses/courses/single/chapters/single/resources/ChapterProblemCard/ChapterProblemCard.scss b/judgels-client/src/routes/courses/courses/single/chapters/single/resources/ChapterProblemCard/ChapterProblemCard.scss index b884e3fa5..f999bf1c1 100644 --- a/judgels-client/src/routes/courses/courses/single/chapters/single/resources/ChapterProblemCard/ChapterProblemCard.scss +++ b/judgels-client/src/routes/courses/courses/single/chapters/single/resources/ChapterProblemCard/ChapterProblemCard.scss @@ -9,15 +9,19 @@ .chapter-problem-card__heading { display: flex; + gap: 10px; } h4 { - flex-grow: 1; - margin-left: 10px; + flex: 1 1; margin-bottom: 0; } .bp4-icon { padding-top: 1px; } + + .bp4-tag { + height: 21px; + } }