-
- Thêm ghi chú tại
- {convertSecondToMinute(second)}
-
-
+ };
+ return (
+
+
+ Thêm ghi chú tại
+ {convertSecondToMinute(second)}
+
+
+
+
-
-
-
+
+
+
+
-
+ );
}
-export default Drawer;
\ No newline at end of file
+export default Drawer;
diff --git a/src/components/filter-course/FilterCourse.style.scss b/src/components/filter-course/FilterCourse.style.scss
index 36d0703..4671e12 100644
--- a/src/components/filter-course/FilterCourse.style.scss
+++ b/src/components/filter-course/FilterCourse.style.scss
@@ -1,81 +1,112 @@
+@use "../../styles/mixins" as *;
+
.filter-course-container {
+ display: flex;
+ gap: 10px;
+
+ .filter-right-course-left {
+ flex: 3;
+
+ img {
+ width: 100%;
+ object-fit: cover;
+ }
+ }
+
+ .filter-right-course-middle {
+ flex: 6;
display: flex;
- gap: 10px;
+ flex-direction: column;
+ justify-content: flex-start;
+ gap: 5px;
- .filter-right-course-left {
- flex: 2;
+ .filter-right-course-title {
+ font-size: 1.6rem;
+ line-height: 1.2;
+ font-weight: 700;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ word-break: break-word;
- img {
- width: 100%;
- height: 135px;
- object-fit: cover;
- }
+ @include screen(md) {
+ font-size: 1.4rem;
+ }
}
- .filter-right-course-middle {
- flex: 6;
- display: flex;
- flex-direction: column;
- justify-content: flex-start;
- gap: 5px;
+ .filter-right-course-desc {
+ font-size: 1.3rem;
- .filter-right-course-title {
- font-size: 16px;
- line-height: 1.2;
- letter-spacing: 0;
- font-weight: 700;
- }
+ @include screen(md) {
+ font-size: 1.1rem;
+ }
+ }
- .filter-right-course-desc {
- font-size: 13px;
- color: #2d2f31;
- }
+ .filter-right-course-instructor {
+ font-size: 1.4rem;
+ font-weight: 500;
- .filter-right-course-instructor {
- font-size: 13px;
- color: #2d2f31;
- }
+ @include screen(md) {
+ font-size: 1.2rem;
+ }
+ }
- .filter-right-course-rating {
- font-size: 13px;
- color: #2d2f31;
- display: flex;
- align-items: center;
- justify-content: flex-start;
- gap: 5px;
-
- .rating {
- font-size: 12px;
- }
- }
+ .filter-right-course-rating {
+ font-size: 1.3rem;
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ gap: 5px;
+ flex-wrap: wrap;
+
+ @include screen(md) {
+ font-size: 1.1rem;
+ }
- .filter-right-course-total {
- font-size: 13px;
- color: #2d2f31;
- display: flex;
- align-items: center;
- justify-content: flex-start;
- gap: 10px;
+ .rating {
+ font-size: 1.2rem;
+
+ @include screen(md) {
+ font-size: 1.1rem;
}
+ }
+ }
+ .filter-right-course-total {
+ font-size: 1.3rem;
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ gap: 10px;
+ flex-wrap: wrap;
+
+ @include screen(md) {
+ font-size: 1.1rem;
+ gap: 5px;
+ }
}
+ }
- .filter-right-course-right {
- flex: 2;
- display: flex;
- justify-content: flex-end;
- font-weight: bold;
- gap: 8px;
-
- .course-discountPrice {
- text-decoration: line-through;
- color: gray;
- font-size: 12px;
- }
+ .filter-right-course-right {
+ flex: 2;
+ display: flex;
+ justify-content: flex-end;
+ font-weight: 700;
+ gap: 8px;
+
+ @include screen(md) {
+ font-size: 1.2rem;
}
- &:hover {
- cursor: pointer;
+ .course-discountPrice {
+ text-decoration: line-through;
+ font-size: 1.2rem;
}
+ }
-}
\ No newline at end of file
+ &:hover {
+ cursor: pointer;
+ }
+}
diff --git a/src/components/footer/Footer.style.scss b/src/components/footer/Footer.style.scss
index aaf2884..3f97847 100644
--- a/src/components/footer/Footer.style.scss
+++ b/src/components/footer/Footer.style.scss
@@ -1,104 +1,99 @@
@use "../../styles/mixins" as *;
.footer {
- background-color: var(--body-bg-second);
+ background-color: var(--body-bg-second);
}
.footer__top {
- padding: 92px 0px 50px;
+ padding: 92px 0px 50px;
- @include screen(lg) {
- padding: 50px 0px 30px;
- }
+ @include screen(lg) {
+ padding: 50px 0px 30px;
+ }
- border-bottom: 1px solid var(--border-color);
+ border-bottom: 1px solid var(--border-color);
- .heading {
- font-size: 2rem;
- font-weight: 700;
- line-height: 150%;
- margin-bottom: 15px;
- }
+ .heading {
+ font-size: 2rem;
+ font-weight: 700;
+ line-height: 150%;
+ margin-bottom: 15px;
+ }
- .link {
- font-size: 1.6rem;
- line-height: 175%;
- padding: 12px 0;
+ .link {
+ font-size: 1.6rem;
+ line-height: 175%;
+ padding: 12px 0;
- &:hover {
- color: var(--primary-color);
- }
+ &:hover {
+ color: var(--primary-color);
}
-
- .heading__small {
- font-size: 1.6rem;
- font-weight: 700;
- line-height: 162.5%;
- margin-bottom: 15px;
- }
-
- .desc {
- font-size: 2rem;
- font-weight: 500;
- line-height: 150%;
- }
-
- .socials {
- margin-top: 24px;
- display: flex;
- gap: 12px; // add spacing between items
-
- .social {
- width: 36px;
- height: 36px;
- display: flex;
- align-items: center;
- justify-content: center;
- border-radius: 50%; // round button
- background-color: var(--body-bg-second); // default background
- transition: all 0.3s ease;
- cursor: pointer;
-
- .icon {
- font-size: 18px;
- color: #555; // default icon color
- transition: color 0.3s ease;
- }
-
- &:hover {
- background-color: var(--primary-color); // highlight on hover
- transform: translateY(-2px); // subtle lift
- box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
-
-
- }
- }
+ }
+
+ .heading__small {
+ font-size: 1.6rem;
+ font-weight: 700;
+ line-height: 162.5%;
+ margin-bottom: 15px;
+ }
+
+ .desc {
+ font-size: 1.6rem;
+ font-weight: 500;
+ line-height: 150%;
+ }
+
+ .socials {
+ margin-top: 24px;
+ display: flex;
+ gap: 12px; // add spacing between items
+
+ .social {
+ width: 36px;
+ height: 36px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 50%; // round button
+ background-color: var(--body-bg-second); // default background
+ transition: all 0.3s ease;
+ cursor: pointer;
+
+ .icon {
+ font-size: 18px;
+ color: #555; // default icon color
+ transition: color 0.3s ease;
+ }
+
+ &:hover {
+ background-color: var(--primary-color); // highlight on hover
+ transform: translateY(-2px); // subtle lift
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
+ }
}
-
+ }
}
.footer__bottom {
- padding: 32px 0;
- display: flex;
- justify-content: space-between;
-
- @include screen(lg) {
- flex-direction: column;
- align-items: center;
- gap: 20px;
+ padding: 32px 0;
+ display: flex;
+ justify-content: space-between;
+
+ @include screen(lg) {
+ flex-direction: column;
+ align-items: center;
+ gap: 20px;
+ }
+
+ .copyright {
+ font-size: 1.6rem;
+ line-height: 162.5%;
+ }
+
+ @include screen(sm) {
+ .logo {
+ position: static;
+ margin-left: 84px;
}
-
- .copyright {
- font-size: 1.6rem;
- line-height: 162.5%;
- }
-
-
- @include screen(sm) {
- .logo {
- position: static;
- margin-left: 84px;
- }
- }
-
-}
\ No newline at end of file
+ }
+}
diff --git a/src/components/header/Header.style.scss b/src/components/header/Header.style.scss
index 6befa32..864662f 100644
--- a/src/components/header/Header.style.scss
+++ b/src/components/header/Header.style.scss
@@ -1,487 +1,478 @@
@use "../../styles/mixins" as *;
.header {
- --nav-right: 60%;
- --multi-level-menu-height: 500px;
- position: relative;
- padding: 20px 0;
- background: var(--header-bg);
- box-shadow: 0 20px 60px 10px var(--header-shadow-bg);
-
- @include screen(sm) {
- --nav-right: 50%;
- }
+ --nav-right: 40%;
+ --multi-level-menu-height: 500px;
+ position: relative;
+ padding: 20px 0;
+ background: var(--header-bg);
+ box-shadow: 0 20px 60px 10px var(--header-shadow-bg);
}
.header__link {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 10px 20px;
- transition: color, background;
- transition-duration: 0.25s;
-
- &-text {
- font-size: 1.4rem;
- line-height: 1.4;
- }
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0 20px;
+ transition: color, background;
+ transition-duration: 0.25s;
+
+ &-text {
+ font-size: 1.4rem;
+ line-height: 1.4;
+ padding: 10px 0;
+ }
+ &:hover {
+ color: var(--primary-color);
+ background: var(--bg-primary-color);
+ }
- &:hover {
- color: var(--primary-color);
- background: var(--bg-primary-color);
- }
-
- &:hover>.icon {
- filter: var(--primary-icon-color);
- }
+ &:hover > .icon {
+ filter: var(--primary-icon-color);
+ }
}
.header__inner {
- position: relative;
- display: flex;
- align-items: center;
- justify-content: space-between;
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
}
-
.header-avatar {
- &__img {
- width: 40px;
- height: 40px;
- object-fit: cover;
- border-radius: 50%;
- }
+ &__img {
+ width: 40px;
+ height: 40px;
+ object-fit: cover;
+ border-radius: 50%;
+ }
}
-
-
.navbar {
+ &__inner {
+ &:hover {
+ .dropdown {
+ opacity: 1;
+ visibility: visible;
+ }
- &__inner {
- &:hover {
- .dropdown {
- opacity: 1;
- visibility: visible;
- }
-
- .header-category {
- color: var(--primary-color); // đổi màu text khi hover để show dropdown
- }
- }
+ .header-category {
+ color: var(--primary-color); // đổi màu text khi hover để show dropdown
+ }
}
+ }
- @include screen(lg) {
- background: var(--header-bg);
- position: fixed;
- top: 0;
- bottom: 0;
- left: -100vw;
- width: calc(100vw - var(--nav-right));
- z-index: 9;
- box-shadow: 0 10px 30px rgba(0, 0, 0, .1);
- transition: left .3s ease;
-
- &.show {
- left: 0;
- }
-
- &.show~&__overlay {
- opacity: 1;
- visibility: visible;
- }
-
- &.show~&__dismiss {
- opacity: 1;
- visibility: visible;
- pointer-events: auto;
- transform: none;
- }
-
- &.show .dropdown {
- opacity: 1;
- visibility: visible;
- left: 0;
- right: 0;
- padding-top: 0;
- }
-
- &.show .dropdown__inner {
- background-color: transparent;
- }
- }
+ @include screen(lg) {
+ background: var(--header-bg);
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ left: -100vw;
+ width: calc(100vw - var(--nav-right));
+ z-index: 9;
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
+ transition: left 0.3s ease;
- @include screen(sm) {
- // width: calc(100vw - 50%);
- --nav-right: 50%;
+ &.show {
+ left: 0;
}
- &__overlay {
- opacity: 0;
- visibility: hidden;
-
- @include screen(lg) {
- position: fixed;
- inset: 0;
- z-index: 8;
- transition: opacity, visibility;
- transition-duration: 0.5s;
- background: rgba($color: #000000, $alpha: 0.4);
- }
+ &.show ~ &__overlay {
+ opacity: 1;
+ visibility: visible;
}
-
- &__dismiss {
- position: fixed;
- /* đặt tại mép phải của navbar + 8px (ra ngoài) */
- left: calc(100vw - var(--nav-right) + 12px);
- top: calc(env(safe-area-inset-top, 0) + 12px);
-
- z-index: 10001; // cao hơn navbar & overlay
- width: 44px;
- height: 44px; // tap target tốt
- display: grid;
- place-items: center;
- background: #fff;
- border: 1px solid #e8e8e8;
- border-radius: 999px;
- box-shadow: 0 6px 20px rgba(0, 0, 0, .12);
- cursor: pointer;
-
- opacity: 0;
- visibility: hidden;
- pointer-events: none;
- transform: translateX(-8px);
- transition: opacity .2s ease, visibility .2s ease, transform .2s ease;
+ &.show .dropdown {
+ opacity: 1;
+ visibility: visible;
+ left: 0;
+ right: 0;
+ padding-top: 0;
}
-}
-
+ &.show .dropdown__inner {
+ background-color: transparent;
+ }
+ }
+ // @include screen(sm) {
+ // --nav-right: 50%;
+ // }
-.dropdown {
+ &__overlay {
opacity: 0;
visibility: hidden;
- position: absolute;
- left: 129px;
- padding-top: 15px;
- transition: opacity visibility;
- transition-duration: 0.25s;
- z-index: 7;
-
-
-
- &__inner {
- background-color: var(--header-bg);
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
- position: relative;
- width: 260px;
- height: var(--multi-level-menu-height);
-
- @include screen(lg) {
- width: 100%;
- height: 100vh;
- overflow-y: auto;
- }
-
- .dropdown__action {
- border-bottom: 2px solid var(--border-color);
- }
-
- .dropdown__btn {
- min-width: 100%;
- justify-content: flex-start;
- padding-left: 15px;
- }
- }
-
+ @include screen(lg) {
+ position: fixed;
+ inset: 0;
+ z-index: 8;
+ transition: opacity, visibility;
+ transition-duration: 0.5s;
+ background: rgba($color: #000000, $alpha: 0.4);
+ }
+ }
+
+ // &__dismiss {
+ // position: fixed;
+ // left: calc(100vw - var(--nav-right) + 12px);
+ // top: calc(env(safe-area-inset-top, 0) + 12px);
+
+ // z-index: 10001; // cao hơn navbar & overlay
+ // width: 44px;
+ // height: 44px; // tap target tốt
+ // display: grid;
+ // place-items: center;
+ // background: #fff;
+ // border: 1px solid #e8e8e8;
+ // border-radius: 999px;
+ // box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
+ // cursor: pointer;
+
+ // opacity: 0;
+ // visibility: hidden;
+ // pointer-events: none;
+ // transform: translateX(-8px);
+ // transition: opacity 0.2s ease, visibility 0.2s ease, transform 0.2s ease;
+ // }
}
-.header-category {
-
- &__item {
- padding-right: 5px;
-
- @include screen(lg) {
- width: 100%;
- }
- }
-
- .navbar:not(.show) &__item:hover>.header-category__submenu {
- opacity: 1;
- visibility: visible;
- }
-
- .navbar:not(.show) &__item:has(.header-category__submenu:hover)>.header__link {
- // background: var(--bg-primary-color);
- color: var(--primary-color);
- }
-
- .navbar:not(.show) &__item:has(.header-category__submenu:hover)>.header__link>.icon {
- filter: var(--primary-icon-color);
- }
+.header__dismiss {
+ position: absolute;
+ right: calc(var(--nav-right) - 80px);
+ top: 0px;
+ z-index: 10;
}
-.header-submenu__heading {
- padding: 10px 20px;
- font-size: 1.6rem;
- line-height: 1.4;
- font-weight: 500;
+.navbar-dismiss {
+ width: 44px;
+ height: 44px;
+ background: #fff;
+ border: 1px solid #e8e8e8;
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
}
-
-.header__submenu-top {
- padding: 10px 20px;
- display: flex;
- align-items: center;
- background-color: var(--header-menu-top);
- gap: 10px;
- font-size: 1.6rem;
- line-height: 1.4;
+.cart_quantity {
+ position: absolute;
+ top: 0;
+ right: 0;
+ background: var(--primary-color);
+ color: white;
+ font-size: 1.4rem;
+ width: 20px;
+ height: 20px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
}
-
-.header-category__submenu {
- opacity: 0;
- visibility: hidden;
- position: absolute;
- top: 0;
- left: 100%;
- background: var(--header-bg);
+.dropdown {
+ opacity: 0;
+ visibility: hidden;
+ position: absolute;
+ left: 129px;
+ padding-top: 15px;
+ transition: opacity visibility;
+ transition-duration: 0.25s;
+ z-index: 7;
+
+ &__inner {
+ background-color: var(--header-bg);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
- transition: opacity visibility;
- transition-duration: 0.25s;
+ position: relative;
width: 260px;
height: var(--multi-level-menu-height);
@include screen(lg) {
- position: fixed;
- width: auto;
- inset: 0 60% 0 0;
- box-shadow: 0 10px 30px rgba(0, 0, 0, .1);
- z-index: 10;
- transform: translateX(100%);
- transition: transform .3s ease, opacity .25s, visibility .25s;
- opacity: 0;
- visibility: hidden;
- pointer-events: none;
- height: 100%;
- }
-
- @include screen(sm) {
- inset: 0 50% 0 0;
+ width: 100%;
+ height: 100vh;
+ overflow-y: auto;
}
-
- &-item {
- padding-right: 5px;
-
+ .dropdown__action {
+ border-bottom: 2px solid var(--border-color);
}
- .navbar:not(.show) &-item:hover>.header-topic__submenu {
- opacity: 1;
- visibility: visible;
+ .dropdown__btn {
+ min-width: 100%;
+ justify-content: flex-start;
+ padding-left: 15px;
}
+ }
+}
- .navbar:not(.show) &-item:has(.header-topic__submenu:hover)>.header__link {
- color: var(--primary-color);
- }
+.header-category {
+ &__item {
+ padding-right: 5px;
- .navbar:not(.show) &-item:has(.header-topic__submenu:hover)>.header__link>.icon {
- filter: var(--primary-icon-color);
- }
+ @include screen(lg) {
+ width: 100%;
+ }
+ }
+
+ .navbar:not(.show) &__item:hover > .header-category__submenu {
+ opacity: 1;
+ visibility: visible;
+ }
+
+ .navbar:not(.show)
+ &__item:has(.header-category__submenu:hover)
+ > .header__link {
+ // background: var(--bg-primary-color);
+ color: var(--primary-color);
+ }
+
+ .navbar:not(.show)
+ &__item:has(.header-category__submenu:hover)
+ > .header__link
+ > .icon {
+ filter: var(--primary-icon-color);
+ }
+}
+.header-submenu__heading {
+ padding: 10px 20px;
+ font-size: 1.6rem;
+ line-height: 1.4;
+ font-weight: 500;
+}
+.header__submenu-top {
+ padding: 10px 20px;
+ display: flex;
+ align-items: center;
+ background-color: var(--header-menu-top);
+ gap: 10px;
+ font-size: 1.6rem;
+ line-height: 1.4;
}
+.header-category__submenu {
+ opacity: 0;
+ visibility: hidden;
+ position: absolute;
+ top: 0;
+ left: 100%;
+ background: var(--header-bg);
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+ transition: opacity visibility;
+ transition-duration: 0.25s;
+ width: 260px;
+ height: var(--multi-level-menu-height);
+
+ @include screen(lg) {
+ position: fixed;
+ width: auto;
+ inset: 0 40% 0 0;
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
+ z-index: 10;
+ transform: translateX(100%);
+ transition: transform 0.3s ease, opacity 0.25s, visibility 0.25s;
+ opacity: 0;
+ visibility: hidden;
+ pointer-events: none;
+ height: 100%;
+ }
+
+ @include screen(sm) {
+ inset: 0 40% 0 0;
+ }
+
+ &-item {
+ padding-right: 5px;
+ }
+
+ .navbar:not(.show) &-item:hover > .header-topic__submenu {
+ opacity: 1;
+ visibility: visible;
+ }
+
+ .navbar:not(.show) &-item:has(.header-topic__submenu:hover) > .header__link {
+ color: var(--primary-color);
+ }
+
+ .navbar:not(.show)
+ &-item:has(.header-topic__submenu:hover)
+ > .header__link
+ > .icon {
+ filter: var(--primary-icon-color);
+ }
+}
.header-topic__submenu {
+ opacity: 0;
+ visibility: hidden;
+ position: absolute;
+ top: 0;
+ left: 100%;
+ transition: opacity visibility;
+ transition-duration: 0.25s;
+ background: var(--header-bg);
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+ width: 260px;
+ height: var(--multi-level-menu-height);
+
+ @include screen(lg) {
+ position: fixed;
+ inset: 0 40% 0 0;
+ width: 100%;
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
+ z-index: 11;
+ transform: translateX(100%);
+ transition: transform 0.3s ease, opacity 0.25s, visibility 0.25s;
opacity: 0;
visibility: hidden;
- position: absolute;
- top: 0;
- left: 100%;
- transition: opacity visibility;
- transition-duration: 0.25s;
- background: var(--header-bg);
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
- width: 260px;
- height: var(--multi-level-menu-height);
-
- @include screen(lg) {
- position: fixed;
- inset: 0 60% 0 0;
- width: 100%;
- box-shadow: 0 10px 30px rgba(0, 0, 0, .1);
- z-index: 11;
- transform: translateX(100%);
- transition: transform .3s ease, opacity .25s, visibility .25s;
- opacity: 0;
- visibility: hidden;
- pointer-events: none;
- height: 100%;
- }
-
- @include screen(sm) {
- inset: 0 50% 0 0;
- }
+ pointer-events: none;
+ height: 100%;
+ }
+ @include screen(sm) {
+ inset: 0 40% 0 0;
+ }
}
@include screen(lg) {
- .header-category__item.is-open>.header-category__submenu {
- transform: translateX(0);
- opacity: 1;
- visibility: visible;
- pointer-events: auto;
- }
-
- .header-category__submenu-item.is-open>.header-topic__submenu {
- transform: translateX(0);
- opacity: 1;
- visibility: visible;
- pointer-events: auto;
- }
-
+ .header-category__item.is-open > .header-category__submenu {
+ transform: translateX(0);
+ opacity: 1;
+ visibility: visible;
+ pointer-events: auto;
+ }
+
+ .header-category__submenu-item.is-open > .header-topic__submenu {
+ transform: translateX(0);
+ opacity: 1;
+ visibility: visible;
+ pointer-events: auto;
+ }
}
-
.header-left {
- display: flex;
- align-items: center;
- gap: 20px;
+ display: flex;
+ align-items: center;
+ gap: 20px;
}
-
.header-menu {
- display: flex;
- align-items: center;
+ display: flex;
+ align-items: center;
- &__icon {
- display: block;
- font-size: 20px;
- }
+ &__icon {
+ display: block;
+ font-size: 20px;
+ }
}
-
.header-language__icon {
- font-size: 1.8rem;
- display: block;
- filter: brightness(0) saturate(100%) invert(100%) sepia(11%) saturate(179%) hue-rotate(230deg) brightness(110%) contrast(103%);
- // opacity: 0.7;
+ font-size: 1.8rem;
+ display: block;
+ filter: brightness(0) saturate(100%) invert(100%) sepia(11%) saturate(179%)
+ hue-rotate(230deg) brightness(110%) contrast(103%);
+ // opacity: 0.7;
}
-
.header-action {
- display: flex;
- align-items: center;
- gap: 20px;
-
- .header-action__login {
- min-width: 90px;
- }
+ display: flex;
+ align-items: center;
+ gap: 20px;
- @include screen(md) {
- margin-left: auto;
- }
-
- @include screen(md) {
- gap: 5px;
- }
+ .header-action__login {
+ min-width: 90px;
+ }
+ @include screen(md) {
+ margin-left: auto;
+ }
+ @include screen(md) {
+ gap: 5px;
+ }
}
.header-action__search-btn {
- max-width: 30px;
- padding: 0;
+ max-width: 30px;
+ padding: 0;
- .header-action__search-icon {
- font-size: 24px;
- padding-top: 5px;
- }
+ .header-action__search-icon {
+ font-size: 24px;
+ padding-top: 5px;
+ }
}
-
.header-form__wrapper:has(:not(.show)) .header-form__cancel {
- display: none;
+ display: none;
}
.header-form__wrapper {
- @include screen(md) {
- margin-left: auto;
- }
-
- &.show {
- position: fixed;
- inset: 0;
- padding: 5px;
- background-color: var(--body-bg);
- z-index: 11;
-
- .header-form {
- display: inline-flex;
- align-items: center;
- width: 100%;
- position: relative;
-
- &__cancel {
- display: inline-block;
- font-size: 1.4rem;
- height: 30px;
- }
- }
+ @include screen(md) {
+ margin-left: auto;
+ }
+
+ &.show {
+ position: fixed;
+ inset: 0;
+ padding: 5px;
+ background-color: var(--body-bg);
+ z-index: 11;
+
+ .header-form {
+ display: inline-flex;
+ align-items: center;
+ width: 100%;
+ position: relative;
+
+ &__cancel {
+ display: inline-block;
+ font-size: 1.4rem;
+ height: 30px;
+ }
}
+ }
}
-
-
-
.header-form {
- display: flex;
- height: 45px;
- width: var(--header-form-width);
-
- border: 2px solid var(--header-form-border-color);
- border-radius: 20px;
- transition: border-color 0.2s ease-in-out;
+ display: flex;
+ height: 45px;
+ width: var(--header-form-width);
+ border: 2px solid var(--header-form-border-color);
+ border-radius: 20px;
+ transition: border-color 0.2s ease-in-out;
+ @include screen(sm) {
+ display: none;
+ }
- @include screen(sm) {
- display: none;
- }
-
-
- &__input {
- flex: 1;
+ &__input {
+ flex: 1;
- &::placeholder {
- font-size: 1.4rem;
- }
+ &::placeholder {
+ font-size: 1.4rem;
}
+ }
- &__icon {
- width: 30px;
- height: 100%;
- opacity: 0.7;
- cursor: pointer;
- transition: opacity .2s ease-in-out;
+ &__icon {
+ width: 30px;
+ height: 100%;
+ opacity: 0.7;
+ cursor: pointer;
+ transition: opacity 0.2s ease-in-out;
- &:hover {
- opacity: 1;
- }
+ &:hover {
+ opacity: 1;
}
+ }
- &__btn {
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 0 10px;
- }
+ &__btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0 10px;
+ }
- &:focus-within {
- border-color: var(--header-search-border-color);
- }
-}
\ No newline at end of file
+ &:focus-within {
+ border-color: var(--header-search-border-color);
+ }
+}
diff --git a/src/components/header/index.tsx b/src/components/header/index.tsx
index 4fa36f6..b99bff9 100644
--- a/src/components/header/index.tsx
+++ b/src/components/header/index.tsx
@@ -1,12 +1,12 @@
import { Link, useNavigate } from "react-router-dom";
import { FiShoppingCart } from "react-icons/fi";
import {
- MdKeyboardArrowLeft,
- MdKeyboardArrowRight,
- MdMenu,
- MdOutlineKeyboardArrowRight,
- MdOutlineNotifications,
- MdSearch,
+ MdKeyboardArrowLeft,
+ MdKeyboardArrowRight,
+ MdMenu,
+ MdOutlineKeyboardArrowRight,
+ MdOutlineNotifications,
+ MdSearch,
} from "react-icons/md";
import "./Header.style.scss";
import Button from "../button";
@@ -26,7 +26,10 @@ import PopoverSearch from "../popover-search";
import { getCartsByUser } from "../../redux/slices/CartSlice";
import { getLearningCourse } from "../../redux/slices/LearningCourseSlice";
import { CourseGetType } from "../../types/CourseType";
-import { getCourseByMultiQuery, getSuggestions } from "../../services/CourseService";
+import {
+ getCourseByMultiQuery,
+ getSuggestions,
+} from "../../services/CourseService";
import { getTopicsByCategoryId } from "../../services/TopicService";
import { TopicType } from "../../pages/admin/topic/TopicType";
import Logo from "../logo";
@@ -36,384 +39,534 @@ import { FaTimes } from "react-icons/fa";
import { LangCode } from "../../types/LanguageType";
import PopoverLanguage from "../popover-language";
function Header() {
- const dispatch = useAppDispatch();
- const navigate = useNavigate();
- const { categoryParents } = useAppSelector((state: RootState) => state.categories);
- const { auth, isLoggin } = useAppSelector((state: RootState) => state.auth);
- const { carts } = useAppSelector((state: RootState) => state.carts);
- const cartTotal = carts ? carts.length : 0;
- const [toggleNavbar, setToggleNavbar] = useState
(false);
- const [open, setOpen] = useState(false);
- const [openSearch, setOpenSearch] = useState(false);
- const [openProfile, setOpenProfile] = useState(false);
- const [openLearning, setOpenLearning] = useState(false);
- const [openLanguage, setOpenLanguage] = useState(false);
- const [openFilter, setOpenFilter] = useState(false);
- const [suggestions, setSuggestions] = useState();
-
- const [keyword, setKeyword] = useState("");
- const [deferredKeyword, setDeferredKeyword] = useState("");
- const [isPending, startTransition] = useTransition();
- const [topics, setTopics] = useState([]);
- const [activeParentId, setActiveParentId] = useState(null);
- const [activeChildId, setActiveChildId] = useState(null);
- const [lang, setLang] = useState("vi");
-
- const handleChangeLang = (code: LangCode) => {
- setLang(code);
- setOpenLanguage(false);
- };
-
- const handleOpenSubmenu = (parentId: number) => (e: any) => {
- e.preventDefault();
- if (toggleNavbar == true) {
- setActiveParentId(parentId);
- }
- };
-
- const handleOpenSubmenuTopic = (childId: number) => (e: any) => {
- e.preventDefault();
- if (toggleNavbar == true) {
- setActiveChildId(childId);
- }
- };
-
- const backToRoot = () => {
- setActiveParentId(null);
- if (activeChildId != null) {
- setActiveChildId(null);
- }
- };
-
- const backToChild = () => setActiveChildId(null);
-
- const isOpen = openSearch && keyword.trim() !== "";
-
- const handleChangeKeyword = async (e: React.ChangeEvent) => {
- const newKeyword = e.target.value;
- console.log(newKeyword);
- setKeyword(newKeyword);
- startTransition(() => {
- setDeferredKeyword(newKeyword);
- setOpenSearch(true);
- });
- };
-
- const handleKeyPress = (event: React.KeyboardEvent) => {
- if (event.key === "Enter") {
- if (keyword && keyword.length > 0) {
- let url = `/courses/search?keyword=${keyword}`;
- navigate(url);
- setOpenSearch(false);
- }
- }
- };
-
- const handleOpenChange = (newOpen: boolean) => {
- setOpen(newOpen);
- };
- const handleOpenProfileChange = (newOpen: boolean) => {
- setOpenProfile(newOpen);
- };
- const handleOpenLearning = (newOpen: boolean) => {
- setOpenLearning(newOpen);
- };
-
- const handleShowFilter = () => {
- setOpenFilter((prev) => !prev);
- };
-
- const handleHideCart = () => {
- setOpen(false);
- };
-
- const getCartTotal = (): string => {
- if (cartTotal > 9) {
- return 9 + "+";
- }
- return cartTotal + "";
- };
-
- const getTopicsByCategory = async (catId: number) => {
- const res = await getTopicsByCategoryId(catId);
- if (res.status == 200) {
- const topics = res.data as TopicType[];
- setTopics(topics);
- } else {
- setTopics([]);
- }
- };
-
- const handleToggleNav = () => {
- setToggleNavbar((prev) => !prev);
- setActiveParentId(null);
- setActiveChildId(null);
- };
-
- useEffect(() => {
- dispatch(fetchCategoryParents());
- if (auth) {
- dispatch(getCartsByUser());
- dispatch(getLearningCourse());
- }
- }, [auth]);
-
- const getSuggestionsByKeyword = async () => {
- const res = await getSuggestions(deferredKeyword);
- if (res.status === 200) {
- const data = res.data as string[];
- setSuggestions(data);
- }
- };
- useEffect(() => {
- getSuggestionsByKeyword();
- }, [deferredKeyword]);
-
- return (
-
-
-
-
-
-
-
-
-
-
diff --git a/src/components/section/index.tsx b/src/components/section/index.tsx
index 1a8f620..fc63645 100644
--- a/src/components/section/index.tsx
+++ b/src/components/section/index.tsx
@@ -3,7 +3,6 @@ import './Section.style.scss'
import { MdModeEdit } from "react-icons/md"
import { FaTrash } from "react-icons/fa"
import { useRef, useState } from "react"
-import 'react-quill/dist/quill.snow.css';
import Curriculum from "../curriculum"
import SectionForm from "../sectionForm"
import CurriculumForm from "../curriculumForm"
@@ -122,4 +121,6 @@ function Section(props: Probs) {
)
}
-export default Section
\ No newline at end of file
+export default Section
+
+// import 'react-quill/dist/quill.snow.css';
diff --git a/src/components/theme/index.tsx b/src/components/theme/index.tsx
index 13db155..4fe2a25 100644
--- a/src/components/theme/index.tsx
+++ b/src/components/theme/index.tsx
@@ -4,7 +4,6 @@ import { RootState } from "../../redux/store";
export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
const theme = useSelector((state: RootState) => state.theme.type);
-
useEffect(() => {
const html = document.documentElement;
diff --git a/src/components/whiteboard/index.tsx b/src/components/whiteboard/index.tsx
index 9c88a1d..723063d 100644
--- a/src/components/whiteboard/index.tsx
+++ b/src/components/whiteboard/index.tsx
@@ -26,9 +26,7 @@ const Whiteboard: React.FC = () => {
const [isDrawing, setIsDrawing] = useState(false);
const [color, setColor] = useState
('#000000');
const [brushSize, setBrushSize] = useState(5);
-
const whiteboardCollection = collection(db, 'whiteboardData');
-
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
diff --git a/src/components/whiteboard/whiteboard.style.scss b/src/components/whiteboard/whiteboard.style.scss
index b65a549..332a2cb 100644
--- a/src/components/whiteboard/whiteboard.style.scss
+++ b/src/components/whiteboard/whiteboard.style.scss
@@ -9,7 +9,6 @@
display: flex;
gap: 10px;
margin-bottom: 10px;
-
button {
padding: 8px 12px;
background-color: #007bff;
diff --git a/src/pages/cart/Cart.style.scss b/src/pages/cart/Cart.style.scss
index 488bac6..3550785 100644
--- a/src/pages/cart/Cart.style.scss
+++ b/src/pages/cart/Cart.style.scss
@@ -9,6 +9,7 @@
font-size: 40px;
font-weight: 700;
line-height: 1.2;
+ width: 12px;
}
.wrapper {
@@ -100,6 +101,7 @@
font-size: 16px;
margin-bottom: 8px;
font-weight: bold;
+ height: 43px;
}
.total-price {
@@ -132,5 +134,4 @@
}
}
}
-
}
\ No newline at end of file
diff --git a/src/pages/cart/index.tsx b/src/pages/cart/index.tsx
index 4296b6e..6ae3c6c 100644
--- a/src/pages/cart/index.tsx
+++ b/src/pages/cart/index.tsx
@@ -1,23 +1,32 @@
-import { Button, Divider, Input } from 'antd';
-import './Cart.style.scss'
-import { LiaTimesSolid } from "react-icons/lia"
-import Course from '../../components/course';
-import { RootState } from '../../redux/store';
-import { useAppSelector } from '../../redux/hooks';
-import { CartType } from '../../types/CartType';
-import { useNavigate } from 'react-router-dom';
-import { getByCode } from '../../services/CouponService';
-import { useState } from 'react';
-import { ErrorType } from '../../types/ErrorType';
-import { CouponType } from '../../types/CouponType';
-import { AxiosError } from 'axios';
-import { formatCurrency } from '../../utils/Format';
+import { Button, Divider, Input } from "antd";
+import "./Cart.style.scss";
+import { LiaTimesSolid } from "react-icons/lia";
+import Course from "../../components/course";
+import { RootState } from "../../redux/store";
+import { useAppSelector } from "../../redux/hooks";
+import { CartType } from "../../types/CartType";
+import { useNavigate } from "react-router-dom";
+import { getByCode } from "../../services/CouponService";
+import { useState } from "react";
+import { ErrorType } from "../../types/ErrorType";
+import { CouponType } from "../../types/CouponType";
+import { AxiosError } from "axios";
+import { formatCurrency } from "../../utils/Format";
function Cart() {
const { carts } = useAppSelector((state: RootState) => state.carts);
- const navigate = useNavigate()
+ const navigate = useNavigate();
const cartLength = carts ? carts.length : 0;
- const totalPrice = carts ? carts.reduce((total, item) => item.buyLater == false ? (total + (item.course.price != item.course.discountedPrice ? item.course.discountedPrice : item.course.price)) : total, 0) : 0
- const cartBuyLaters = carts && carts.filter(item => item.buyLater) as CartType[]
+ const totalPrice = carts
+ ? carts.reduce(
+ (total, item) =>
+ item.buyLater == false
+ ? total +
+ (item.course.price != item.course.discountedPrice ? item.course.discountedPrice : item.course.price)
+ : total,
+ 0
+ )
+ : 0;
+ const cartBuyLaters = carts && (carts.filter((item) => item.buyLater) as CartType[]);
const cartBuyLaterLength = cartBuyLaters ? cartBuyLaters.length : 0;
const [disabledDiscount, setDisabledDiscount] = useState(false);
const [couponValue, setCouponValue] = useState("");
@@ -26,27 +35,26 @@ function Cart() {
const getTotalPrice = (): number => {
if (coupon) {
- const newTotal = totalPrice - coupon.discountPercent * totalPrice / 100
+ const newTotal = totalPrice - (coupon.discountPercent * totalPrice) / 100;
return newTotal;
}
return totalPrice;
- }
+ };
const handleCancelCoupon = () => {
setCoupon(undefined);
- setDisabledDiscount(false)
+ setDisabledDiscount(false);
setCouponValue("");
- }
+ };
const handleRedirectToPaymentPage = () => {
if (coupon) {
const url = `/payment/checkout/?discountPercent=${coupon.discountPercent}&couponCode=${coupon.code}`;
console.log(url);
- navigate(url)
+ navigate(url);
} else {
- navigate("/payment/checkout")
+ navigate("/payment/checkout");
}
-
- }
+ };
const handleSearchCoupon = async () => {
try {
const res = await getByCode(couponValue);
@@ -68,63 +76,81 @@ function Cart() {
setErrorMessage(message);
}
}
- }
+ };
const handleChangeCouponValue = (e: React.ChangeEvent) => {
const counponVal = e.target.value;
setCouponValue(counponVal);
- }
+ };
- return
-
Giỏ hàng
-
-
-
{cartLength} khóa học trong giỏ hàng
- {carts && carts.map((cart) => {
- if (cart.buyLater == false) {
- return
- }
- })}
+ return (
+
+
Giỏ hàng
+
+
+
{cartLength} khóa học trong giỏ hàng
+ {carts &&
+ carts.map((cart) => {
+ if (cart.buyLater == false) {
+ return
;
+ }
+ })}
- {cartBuyLaterLength > 0 &&
Gần đây được thêm vào danh sách mong ước
}
- {cartBuyLaters && cartBuyLaters.map((cart) => {
- if (cart.buyLater == true) {
- return
- }
- })}
-
-
-
-
Tổng
-
{formatCurrency(getTotalPrice())}
- {coupon && <>
-
{formatCurrency(totalPrice)}
-
Giảm {coupon.discountPercent}%
- >}
+ {cartBuyLaterLength > 0 &&
Gần đây được thêm vào danh sách mong ước
}
+ {cartBuyLaters &&
+ cartBuyLaters.map((cart) => {
+ if (cart.buyLater == true) {
+ return
;
+ }
+ })}
-
Thanh toán
-
-
Khuyến mãi
- {coupon &&
-
-
- -
- Đã áp dụng {coupon.code}
-
-
+
+
+
Tổng
+
{formatCurrency(getTotalPrice())}
+ {coupon && (
+ <>
+
{formatCurrency(totalPrice)}
+
Giảm {coupon.discountPercent}%
+ >
+ )}
+
+
+ Thanh toán
+
+
+
Khuyến mãi
+ {coupon && (
+
+
+
+ -
+ Đã áp dụng {coupon.code}
+
+
+
+
+
+
+
+ )}
+
+
+
+ Áp dụng
+
-
-
-
-
}
-
-
- Áp dụng
+ {errorMessage && errorMessage !== "" && {errorMessage}}
- {errorMessage && errorMessage !== "" &&
{errorMessage}}
-
;
+ );
}
-export default Cart;
\ No newline at end of file
+export default Cart;
diff --git a/src/pages/filter/Filter.style.scss b/src/pages/filter/Filter.style.scss
index 3031813..2f49e76 100644
--- a/src/pages/filter/Filter.style.scss
+++ b/src/pages/filter/Filter.style.scss
@@ -1,127 +1,169 @@
-.filter-container {
- display: flex;
- padding: 40px 0;
- gap: 15px;
+@use "../../styles/mixins" as *;
- .filter-left {
- flex: 2;
-
- .filter-form {
- min-width: 100%;
- display: flex;
- flex-direction: column;
- align-items: start;
- padding-right: 40px;
- gap: 15px;
-
- .filter-btn {
- display: flex;
- gap: 10px;
- margin: 0;
- min-width: 100%;
-
- .filter-btn-reset {
- color: var(--color-gray-500);
- background-color: transparent;
- border: 1px solid #2d2f31;
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 10px;
- border-radius: 0;
-
- span {
- font-size: 16px;
- font-weight: 700;
- }
- }
-
- .filter-select-sort {
- display: flex;
- align-items: center;
- justify-content: center;
- flex-direction: column;
-
- .filter-label-sort {
- font-size: 16px;
- }
-
- .filer-selection {
- border-radius: 0;
- width: 300px;
- }
- }
- }
+.filter-container {
+ display: flex;
+ padding: 50px 0;
+ gap: 30px;
+
+ .filter__dismiss {
+ position: absolute;
+ top: 12px;
+ left: calc(min(80%, 400px) + 12px);
+ z-index: 21;
+ cursor: pointer;
+ }
+
+ .filter-dismiss__btn {
+ min-width: 44px;
+ height: 44px;
+ border: 1px solid #e8e8e8;
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
+ @include screen(md) {
+ min-width: 30px !important;
+ height: 30px;
+ }
+ }
+
+ .filter__overlay {
+ opacity: 0;
+ visibility: hidden;
+
+ @include screen(lg) {
+ position: fixed;
+ inset: 0;
+ z-index: 8;
+ transition: opacity, visibility;
+ transition-duration: 0.5s;
+ background: rgba($color: #000000, $alpha: 0.4);
+ }
+ }
+
+ .filter-left {
+ flex: 4;
+
+ @include screen(lg) {
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 80%;
+ max-width: 400px;
+ background: var(--body-bg);
+ box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.1),
+ 6px 0 20px rgba(0, 0, 0, 0.12);
+ z-index: 20;
+ overflow-y: auto;
+
+ transform: translateX(-100%);
+ opacity: 0;
+ pointer-events: none;
+ transition: all 0.3s ease;
+
+ &.open {
+ transform: translateX(0);
+ opacity: 1;
+ pointer-events: auto;
+ }
+
+ &.open ~ .filter__overlay {
+ opacity: 1;
+ visibility: visible;
+ }
+
+ .filter-form__wrapper {
+ padding: 20px;
+ }
+ }
- .filter-form-item {
- display: flex;
- flex-direction: column;
- min-width: 400px;
-
- .filter-form-devider {
- width: 200px !important;
- margin: 0;
- background-color: #d1d7dd;
- }
-
- .filter-form-header {
- color: #2d2f31;
- text-align: left;
- white-space: normal;
- font-size: 19px;
- margin-top: 10px;
- }
-
- .filter-form-content {
- margin-top: 15px;
- font-size: 12px;
-
- .filter-form-content-category {
- display: flex;
- align-items: center;
-
- .radio-cat-name {
- width: 200px;
- }
- }
-
- .filter-form-content-checkbox {
- display: flex;
- align-items: center;
- gap: 10px;
-
- .filter-form-content-rating {
- font-size: 12px;
- }
-
- }
-
- }
- }
- }
+ .filter-form__wrapper {
+ min-width: 100%;
}
- .filter-right {
- flex: 7;
- margin-top: 50px;
+ .filter-form {
+ .filter-btn-reset {
+ min-width: 90px;
+ margin-bottom: 30px;
+ }
+
+ .filter-form-item {
display: flex;
flex-direction: column;
- gap: 20px;
+ min-width: 100%;
- .filter-right-container {
+ .filter-form-devider {
+ // width: 200px !important;
+ margin: 0;
+ background-color: #d1d7dd;
+ }
+
+ .filter-form-header {
+ text-align: left;
+ white-space: normal;
+ font-size: 19px;
+ margin-top: 10px;
+ color: var(--text-color);
+ }
+
+ .filter-form-content {
+ margin-top: 15px;
+ font-size: 12px;
+
+ .filter-form-content-category {
display: flex;
- flex-direction: column;
+ align-items: center;
+
+ .radio-cat-name {
+ width: 200px;
+ }
+ }
+ .filter-form-content-checkbox {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ .filter-form-content-rating {
+ font-size: 12px;
+ margin-right: 5px;
+ }
- .filter-right-course-devider {
- background-color: #d1d7dd;
- width: 100%;
+ .filter-form-content-text {
+ font-size: 1.6rem;
+ color: var(--text-color);
+ @include screen(md) {
+ font-size: 1.4rem;
+ }
}
+ }
}
+ }
+ }
+ }
+ .filter-right {
+ flex: 7;
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+
+ .filter-right__btn {
+ width: 120px;
+ @include screen(md) {
+ font-size: 1.4rem;
+ width: 100px;
+ height: 30px;
+ }
+ }
+ .filter-right-container {
+ display: flex;
+ flex-direction: column;
+ .filter-right-course-devider {
+ background-color: #d1d7dd;
+ width: 100%;
+ }
}
-}
\ No newline at end of file
+ }
+}
diff --git a/src/pages/filter/index.tsx b/src/pages/filter/index.tsx
index baf4c57..53db64f 100644
--- a/src/pages/filter/index.tsx
+++ b/src/pages/filter/index.tsx
@@ -1,311 +1,384 @@
-import { Button, Checkbox, Col, Divider, Form, Pagination, Radio, Rate, Row, Select } from "antd";
+import {
+ Checkbox,
+ Col,
+ Divider,
+ Form,
+ Pagination,
+ Radio,
+ Rate,
+ Row,
+} from "antd";
import "./Filter.style.scss";
-import { Option } from "antd/es/mentions";
-import { IoFilter } from "react-icons/io5";
+import { IoFilter, IoFilterOutline } from "react-icons/io5";
import { useEffect, useState, Fragment } from "react";
import { CourseListGetType } from "../../types/CourseType";
import { getCourseByMultiQuery } from "../../services/CourseService";
import FilterCourse from "../../components/filter-course";
import { getByName } from "../../services/CategoryService";
+import { useLocation } from "react-router-dom";
+import Button from "../../components/button";
+import clsx from "clsx";
+import { FaTimes } from "react-icons/fa";
type filterType = {
- ratingStar: string;
- level: string[];
- free: string[];
- categoryName: string;
+ ratingStar: string;
+ level: string[];
+ free: string[];
+ categoryName: string;
};
function Filter() {
- const [filter, setFilter] = useState
("");
- const [pageNum, setPageNum] = useState(0);
- const [courses, setCourses] = useState();
- const [totalElements, setTotalElements] = useState(0);
- const [form] = Form.useForm();
- const [category, setCategory] = useState();
+ const [filter, setFilter] = useState("");
+ const [pageNum, setPageNum] = useState(0);
+ const [courses, setCourses] = useState();
+ const [totalElements, setTotalElements] = useState(0);
+ const [form] = Form.useForm();
+ const [category, setCategory] = useState();
+ const [openFilter, setOpenFilter] = useState(false);
+ const location = useLocation();
+ const searchParams = new URLSearchParams(location.search);
+ const keyword = searchParams.get("keyword");
+ const catName = searchParams.get("catName");
+ const topicId = searchParams.get("topicId");
- const handleOnValuesChange = (_values: string, allValues: filterType) => {
- let newFilter: string = "";
- console.log(allValues);
+ const handleOnValuesChange = (_values: string, allValues: filterType) => {
+ let newFilter: string = "";
+ console.log(allValues);
- if (allValues.level) {
- allValues.level.forEach((l) => {
- newFilter += `&level=${l}`;
- });
- }
- if (allValues.ratingStar) {
- newFilter += `&ratingStar=${allValues.ratingStar}`;
- }
+ if (allValues.level) {
+ allValues.level.forEach((l) => {
+ newFilter += `&level=${l}`;
+ });
+ }
+ if (allValues.ratingStar) {
+ newFilter += `&ratingStar=${allValues.ratingStar}`;
+ }
- if (allValues.free) {
- allValues.free.forEach((f) => {
- newFilter += `&free=${f}`;
- });
- }
- if (allValues.categoryName) {
- newFilter += `&categoryName=${allValues.categoryName}`;
- }
+ if (allValues.free) {
+ allValues.free.forEach((f) => {
+ newFilter += `&free=${f}`;
+ });
+ }
+ if (allValues.categoryName) {
+ newFilter += `&categoryName=${allValues.categoryName}`;
+ }
- setFilter(newFilter);
- };
- const handleReset = () => {
- form.resetFields();
- setFilter("");
- setPageNum(0);
- };
- const handleChangeCurrent = (value: number) => {
- setPageNum(value);
- };
- useEffect(() => {
- // if (filter == "") {
- // const searchParams = new URLSearchParams(location.search);
- // const keyword = searchParams.get("keyword");
- // const catName = searchParams.get("catName");
- // const topicId = searchParams.get("topicId");
- // if (catName) {
- // fetchCategoryChild(catName);
- // }
- // fetchCourses(keyword, catName, topicId);
- // } else {
- // fetchCourses("", "", "");
- // }
+ setFilter(newFilter);
+ };
+ const handleReset = () => {
+ form.resetFields();
+ setFilter("");
+ setPageNum(0);
+ };
+ const handleChangeCurrent = (value: number) => {
+ setPageNum(value);
+ };
- const searchParams = new URLSearchParams(location.search);
- const keyword = searchParams.get("keyword");
- const catName = searchParams.get("catName");
- const topicId = searchParams.get("topicId");
- if (catName) {
- fetchCategoryChild(catName);
- }
- fetchCourses(keyword, catName, topicId);
- }, [filter, pageNum]);
+ const toggleFilter = () => {
+ setOpenFilter((prev) => !prev);
+ };
+ useEffect(() => {
+ if (catName) {
+ fetchCategoryChild(catName);
+ }
+ fetchCourses();
+ }, [filter, pageNum, keyword, catName, topicId]);
- const fetchCategoryChild = async (catName: string) => {
- const res = await getByName(catName);
- console.log(res);
- if (res.status == 200) {
- const data = res.data as CategoryListGetType;
- setCategory(data);
- }
- };
- const fetchCourses = async (
- keyword: string | undefined | null,
- categoryName: string | undefined | null,
- topicId: string | undefined | null
- ) => {
- let query: string = "";
- if (keyword) {
- query += `&keyword=${keyword}`;
- }
- if (categoryName) {
- query += `&categoryName=${categoryName}`;
- }
- if (topicId) {
- query += `&topicId=${topicId}`;
- }
+ const fetchCategoryChild = async (catName: string) => {
+ const res = await getByName(catName);
+ console.log(res);
+ if (res.status == 200) {
+ const data = res.data as CategoryListGetType;
+ setCategory(data);
+ }
+ };
+ const fetchCourses = async () => {
+ let query: string = "";
+ if (keyword) {
+ query += `&keyword=${keyword}`;
+ }
+ if (catName) {
+ query += filter.includes("categoryName")
+ ? ""
+ : `&categoryName=${catName}`;
+ }
+ if (topicId) {
+ query += `&topicId=${topicId}`;
+ }
- if (filter) {
- query += `&${filter}`;
- }
- if (pageNum) {
- query += `&pageNum=${pageNum - 1}`;
- }
- const res = await getCourseByMultiQuery(query);
+ if (filter) {
+ query += `&${filter}`;
+ }
+ if (pageNum) {
+ query += `&pageNum=${pageNum - 1}`;
+ }
+ const res = await getCourseByMultiQuery(query);
- if (res.status == 200) {
- console.log(res.data);
- const data = res.data;
- const total = data.totalElements;
- setTotalElements(total);
- const content = data.content as CourseListGetType[];
- setCourses(content);
- }
- };
+ if (res.status == 200) {
+ console.log(res.data);
+ const data = res.data;
+ const total = data.totalElements;
+ setTotalElements(total);
+ const content = data.content as CourseListGetType[];
+ setCourses(content);
+ }
+ };
- return (
-
-
-
-
-
- {courses &&
- courses.map((course, index) => {
- return (
-
-
- {index < courses.length - 1 && }
-
- );
- })}
-
-
+ return (
+
+
+
+
+ )}
+
+
+
+
Rating
+
+
+
+
+
+
+
+ 4.5 & ups
+
+
+
+
+
+
+
+ 4.0 & ups
+
+
+
+
+
+
+
+ 3.5 & ups
+
+
+
+
+
+
+
+ 3 & ups
+
+
+
+
+
+
+
+
+
+
Level
+
+
+
+
+
+
+ All Levels
+
+
+
+
+
+
+ Beginner
+
+
+
+
+
+
+ Intermediate
+
+
+
+
+
+
+ Expert
+
+
+
+
+
+
+
+
+
+
Price
+
+
+
+
+
+ Paid
+
+
+
+
+ Free
+
+
+
+
+
+
+
+
+
+ {openFilter && (
+
+
+
+
+
+ )}
+
setOpenFilter(false)}
+ >
+
+
+
}
+ className="filter-right__btn d-none d-lg-flex"
+ onClick={toggleFilter}
+ >
+ All Filters
+
+
+ {courses &&
+ courses.map((course, index) => {
+ return (
+
+
+ {index < courses.length - 1 && (
+
+ )}
+
+ );
+ })}
+
+
- );
+
+
+ );
}
export default Filter;
diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx
index 0250235..1eddddf 100644
--- a/src/pages/profile/index.tsx
+++ b/src/pages/profile/index.tsx
@@ -1,38 +1,37 @@
-import { Button, Col, Form, GetProp, Input, InputNumber, Row, Select, Upload, UploadProps, message } from 'antd';
-import './Profile.style.scss'
-import { useState, useEffect, ChangeEvent } from 'react';
-import { useAppDispatch, useAppSelector } from '../../redux/hooks';
-import { RootState } from '../../redux/store';
-import { StudentType } from '../../types/StudentType';
-import { uploadFile } from '../../services/MediaService';
-import { updateStudent } from '../../services/StudentService';
-import { AuthType } from '../../types/AuthType';
-import { updateUserProfile } from '../../redux/slices/AuthenticationSlice';
-import { AxiosError } from 'axios';
-import { ErrorType } from '../../types/ErrorType';
-
+import { Button, Col, Form, GetProp, Input, InputNumber, Row, Select, Upload, UploadProps, message } from "antd";
+import "./Profile.style.scss";
+import { useState, useEffect, ChangeEvent } from "react";
+import { useAppDispatch, useAppSelector } from "../../redux/hooks";
+import { RootState } from "../../redux/store";
+import { StudentType } from "../../types/StudentType";
+import { uploadFile } from "../../services/MediaService";
+import { updateStudent } from "../../services/StudentService";
+import { AuthType } from "../../types/AuthType";
+import { updateUserProfile } from "../../redux/slices/AuthenticationSlice";
+import { AxiosError } from "axios";
+import { ErrorType } from "../../types/ErrorType";
type Day = {
- value: number
-}
+ value: number;
+};
const day: Day[] = [];
for (let i = 1; i <= 31; i++) {
day.push({
- value: i
- })
+ value: i,
+ });
}
const month: Month[] = [];
type Month = {
- value: number,
- label: string
-}
+ value: number;
+ label: string;
+};
for (let i = 1; i <= 12; i++) {
month.push({
value: i,
- label: `Tháng ${i}`
- })
+ label: `Tháng ${i}`,
+ });
}
function Profile() {
const dispatch = useAppDispatch();
@@ -57,15 +56,15 @@ function Profile() {
photo = res.data.url;
}
}
- values = { ...values, photo: photo }
+ values = { ...values, photo: photo };
if (checkIsChangePassword === false) {
- values = { ...values, password: "" }
+ values = { ...values, password: "" };
}
try {
const resUpdateUser = await updateStudent(values);
if (resUpdateUser.status === 200) {
const data = resUpdateUser.data as AuthType;
- dispatch(updateUserProfile(data))
+ dispatch(updateUserProfile(data));
alert("Update user profile success");
}
} catch (error: AxiosError | any) {
@@ -73,14 +72,12 @@ function Profile() {
console.log(error.response.data);
const data = error.response.data as ErrorType;
const message = data.details;
- alert(message)
+ alert(message);
}
}
-
- }
+ };
const [imageUrl, setImageUrl] = useState
();
-
useEffect(() => {
if (auth) {
const user = auth.user;
@@ -89,12 +86,12 @@ function Profile() {
day: user.dateOfBirth.split("-")[2],
month: user.dateOfBirth.split("-")[1],
year: user.dateOfBirth.split("-")[0],
- })
+ });
setImageUrl(user.photoURL);
}
- }, [])
+ }, []);
const handleFileChange = (event: ChangeEvent) => {
- const files = event.target.files
+ const files = event.target.files;
if (files && files.length > 0) {
const selected = files[0] as File;
const url = URL.createObjectURL(selected);
@@ -102,74 +99,69 @@ function Profile() {
setImageUrl(url);
setFileType(selected);
}
- }
- return ;
+ };
+ return (
+
+ );
}
-export default Profile;
\ No newline at end of file
+export default Profile;
diff --git a/src/pages/register/index.tsx b/src/pages/register/index.tsx
index 3a989a9..9e208a1 100644
--- a/src/pages/register/index.tsx
+++ b/src/pages/register/index.tsx
@@ -18,7 +18,6 @@ function Register() {
} = useForm();
const navigate = useNavigate();
const [loading, setLoading] = useState(false);
-
const onSubmit: SubmitHandler = async (values) => {
setLoading(true);
try {
diff --git a/src/redux/slices/ThemeSlice.tsx b/src/redux/slices/ThemeSlice.tsx
index 3a2dd82..76544d4 100644
--- a/src/redux/slices/ThemeSlice.tsx
+++ b/src/redux/slices/ThemeSlice.tsx
@@ -1,21 +1,21 @@
import { createSlice } from "@reduxjs/toolkit";
export interface ThemeState {
- type: "dark" | "light";
+ type: "dark" | "light";
}
const initialState: ThemeState = {
- type: "light",
+ type: "light",
};
const themeSlice = createSlice({
- name: "theme",
- initialState,
- reducers: {
- toggleTheme(state) {
- state.type = state.type === "dark" ? "light" : "dark";
- },
+ name: "theme",
+ initialState,
+ reducers: {
+ toggleTheme(state) {
+ state.type = state.type === "dark" ? "light" : "dark";
},
+ },
});
export const { toggleTheme } = themeSlice.actions;
diff --git a/src/services/SectionService.tsx b/src/services/SectionService.tsx
index b8c918e..a5197b3 100644
--- a/src/services/SectionService.tsx
+++ b/src/services/SectionService.tsx
@@ -5,10 +5,10 @@ export const create = async (sectionPost: SectionType) => {
const url = "/admin/sections";
const res = await instance.post(url, sectionPost);
return res;
-}
+};
export const update = async (sectionPost: SectionType, sectionId: number | undefined) => {
const url = `/admin/sections/${sectionId}`;
const res = await instance.put(url, sectionPost);
return res;
-}
\ No newline at end of file
+};
diff --git a/src/services/StudentExerciseService.tsx b/src/services/StudentExerciseService.tsx
index bf410df..0534702 100644
--- a/src/services/StudentExerciseService.tsx
+++ b/src/services/StudentExerciseService.tsx
@@ -9,7 +9,7 @@ export const createStudentExercise = async (request: StudentExercisePostType) =>
export const updateStudentExercise = async (request: StudentExercisePostType, id: number) => {
- const url = `/student-exercises/${id}`
+ const url = `/student-exercises/${id}`;
const res = await instance.put(url, request);
return res;
}
diff --git a/src/services/TopicService.tsx b/src/services/TopicService.tsx
index bd030e2..6b08810 100644
--- a/src/services/TopicService.tsx
+++ b/src/services/TopicService.tsx
@@ -2,41 +2,41 @@ import { TopicType } from "../pages/admin/topic/TopicType";
import instance from "../utils/axiosCustomize";
export const getTopicWithPagination = async (current: number, pageSize: number, keyword: string | null) => {
- let url: string = ""
+ let url: string = "";
if (keyword != null) {
- url = `/admin/topics/paging?pageNum=${current}&pageSize=${pageSize}&keyword=${keyword}`
+ url = `/admin/topics/paging?pageNum=${current}&pageSize=${pageSize}&keyword=${keyword}`;
} else {
- url = `/admin/topics/paging?pageNum=${current}&pageSize=${pageSize}`
+ url = `/admin/topics/paging?pageNum=${current}&pageSize=${pageSize}`;
}
const res = await instance.get(url);
return res;
-}
+};
export const save = async (topicPost: TopicType) => {
const url = "/admin/topics";
const res = await instance.post(url, topicPost);
return res;
-}
+};
export const update = async (topicPost: TopicType, topicId: number | undefined) => {
const url = `/admin/topics/${topicId}`;
const res = await instance.put(url, topicPost);
return res;
-}
+};
export const get = async (topicId: number) => {
- const url = `/topics/${topicId}`
+ const url = `/topics/${topicId}`;
const res = await instance.get(url);
return res;
-}
+};
export const deleteTopic = async (topicId: number) => {
- const url = `/admin/topics/${topicId}`
+ const url = `/admin/topics/${topicId}`;
const res = await instance.delete(url);
return res;
-}
+};
export const getTopicsByCategoryId = async (catId: number | undefined) => {
- const url = `/topics/category/${catId}`
+ const url = `/topics/category/${catId}`;
const res = await instance.get(url);
return res;
-}
\ No newline at end of file
+};
diff --git a/src/styles/_grid.scss b/src/styles/_grid.scss
index 9ea8546..f6b6232 100644
--- a/src/styles/_grid.scss
+++ b/src/styles/_grid.scss
@@ -1,5 +1,5 @@
@use "sass:math";
-
+@use "sass:map";
$grid-breakpoints: (
xxl: 1400px,
xl: 1200px,
@@ -116,21 +116,23 @@ $gutters: (
@include make-gutters();
-@each $breakpoint, $dimension in $grid-breakpoints {
- $max-width: map-get($container-max-widths, $breakpoint);
- $infix: "-#{$breakpoint}";
-
- @include make-media-query($dimension) {
- .container {
- max-width: $max-width;
- }
- @include make-row-columns($infix);
+@each $breakpoint, $dimension in $grid-breakpoints {
+ $max-width: map.get($container-max-widths, $breakpoint);
- @include make-columns($infix);
+ $infix: "-#{$breakpoint}";
- @include make-offsets($infix);
- @include make-gutters($infix);
+ @include make-media-query($dimension) {
+ .container {
+ @if map.has-key($container-max-widths, $breakpoint) {
+ max-width: $max-width;
+ }
}
+
+ @include make-row-columns($infix);
+ @include make-columns($infix);
+ @include make-offsets($infix);
+ @include make-gutters($infix);
+ }
}
\ No newline at end of file
diff --git a/src/styles/_mixins.scss b/src/styles/_mixins.scss
index 1e8c28b..fad2f6b 100644
--- a/src/styles/_mixins.scss
+++ b/src/styles/_mixins.scss
@@ -1,3 +1,5 @@
+@use "sass:map";
+
$grid-breakpoints: (
sm: 576px,
md: 768px,
@@ -6,16 +8,15 @@ $grid-breakpoints: (
xxl: 1400px,
);
-@mixin screen($key) {
- $breakpoint: map-get($grid-breakpoints, $key);
- @if ($breakpoint) {
- @media (max-width: ($breakpoint - 0.02)) {
- @content;
- }
- }
+@mixin screen($key) {
+ $breakpoint: map.get($grid-breakpoints, $key);
- @else {
- @error 'The value "#{$key}" is not in breakpoints list.';
+ @if ($breakpoint) {
+ @media (max-width: ($breakpoint - 0.02)) {
+ @content;
}
-}
\ No newline at end of file
+ } @else {
+ @error 'The value "#{$key}" is not in breakpoints list.';
+ }
+}
diff --git a/src/styles/index.scss b/src/styles/index.scss
index 39ceab1..977100d 100644
--- a/src/styles/index.scss
+++ b/src/styles/index.scss
@@ -23,22 +23,28 @@
--bg-color-white: #fff;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-
}
html {
font-size: 62.5%;
- --primary-color: #FF6934;
- --bg-primary-color: #FFB499;
- --primary-icon-color: brightness(0) saturate(100%) invert(75%) sepia(53%) saturate(7082%) hue-rotate(337deg) brightness(100%) contrast(103%);
+ --primary-color: #ff6934;
+ --bg-primary-color: #ffb499;
+ --primary-icon-color: brightness(0) saturate(100%) invert(75%) sepia(53%)
+ saturate(7082%) hue-rotate(337deg) brightness(100%) contrast(103%);
--header-bg: #fff;
--header-menu-top: #eee;
- --header-shadow-bg: rgba(237, 237, 246, 0.20);
- --text-color: #032E32;
- --body-bg: #FFF;
+ --header-shadow-bg: rgba(237, 237, 246, 0.2);
+ --text-color: #032e32;
+ --body-bg: #fff;
--body-bg-second: #f5f5f5;
- --icon-color: brightness(0) saturate(100%) invert(8%) sepia(10%) saturate(4042%) hue-rotate(212deg) brightness(90%) contrast(95%);
+ --icon-color: brightness(0) saturate(100%) invert(8%) sepia(10%)
+ saturate(4042%) hue-rotate(212deg) brightness(90%) contrast(95%);
+
+ // Rating
+ .rating .ant-rate-star-zero .ant-rate-star-second {
+ color: #e8e8e8; // mặc định light
+ }
// Header
--header-search-border-color: #444;
@@ -54,25 +60,23 @@ html {
}
@include screen(md) {
- --header-form-width: 250px;
+ --header-form-width: 270px;
}
-
- // Language
+ // Language
--lang-hover-bg: #f5f5f5;
--lang-active-color: #1677ff;
--lang-active-bg: #e6f4ff;
--popover-bg: #fff;
--popover-arrow-color: #fff;
-
- // Popover search
+ // Popover search
--search-form-w: 420px; // Đặt cùng giá trị width form để 2 bên khớp nhau
--popover-radius: 12px;
--popover-bg: #fff;
--popover-border: #eaecef;
- --popover-shadow: 0 12px 28px rgba(0, 0, 0, .12),
- 0 2px 8px rgba(0, 0, 0, .06);
+ --popover-shadow: 0 12px 28px rgba(0, 0, 0, 0.12),
+ 0 2px 8px rgba(0, 0, 0, 0.06);
--text-1: #1f2328;
--text-2: #57606a;
--item-hover-bg: #f6f8fa;
@@ -88,29 +92,37 @@ html {
// Card
--card-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
- --card-shadow-hover: 0 8px 24px rgba(0, 0, 0, .12);
+ --card-shadow-hover: 0 8px 24px rgba(0, 0, 0, 0.12);
--card-bg: #f0f2f5;
}
html.dark {
- --header-bg: #171C28;
- --header-menu-top: #171C28;
- --header-shadow-bg: rgba(0, 0, 0, 0.20);
- --icon-color: brightness(0) saturate(100%) invert(100%) sepia(0%) saturate(7482%) hue-rotate(72deg) brightness(99%) contrast(99%);
+ --header-bg: #171c28;
+ --header-menu-top: #171c28;
+ --header-shadow-bg: rgba(0, 0, 0, 0.2);
+ --icon-color: brightness(0) saturate(100%) invert(100%) sepia(0%)
+ saturate(7482%) hue-rotate(72deg) brightness(99%) contrast(99%);
--text-color: #fff;
--body-bg: #0f1115;
--body-bg-second: #272a31;
--header-search-border-color: rgb(232, 232, 232);
--header-form-border-color: rgb(249, 249, 251, 0.2);
- // Language
+ // Rating
+ .rating {
+ .ant-rate-star-zero .ant-rate-star-second {
+ color: #4a4a4a;
+ }
+ }
+
+ // Language
--lang-hover-bg: #2a2a2a;
--lang-active-color: #4e9eff;
--lang-active-bg: #1a1a1a;
--popover-bg: #1f1f1f;
--popover-arrow-color: #080606;
- // Popover search
+ // Popover search
--popover-bg: #1f2328;
--popover-border: #2d333b;
--text-1: #e6edf3;
@@ -123,26 +135,62 @@ html.dark {
box-shadow: none;
}
-
- // Popover user profile
+ // Popover user profile
--popover-hover: #3a4050;
--popover-divider: #454c61;
-
// Card
--card-bg: #15171a;
/* sáng hơn nền trang ~6–8% để tách lớp */
--card-shadow: 0 1px 0 rgba(255, 255, 255, 0.04) inset,
- 0 2px 8px rgba(0, 0, 0, 0.45);
+ 0 2px 8px rgba(0, 0, 0, 0.45);
--card-shadow-hover: 0 1px 0 rgba(255, 255, 255, 0.06) inset,
- 0 8px 24px rgba(0, 0, 0, 0.6);
-}
+ 0 8px 24px rgba(0, 0, 0, 0.6);
+ // Pagination
+ .ant-pagination {
+ .ant-pagination-item {
+ border: 1px solid #434343;
+ background-color: transparent;
+ a {
+ color: #bfbfbf;
+ }
+ &:hover {
+ border-color: #1677ff;
+ a {
+ color: #1677ff;
+ }
+ }
+ }
+
+ .ant-pagination-item-active {
+ border-color: #1677ff;
+ background-color: #1677ff;
+
+ a {
+ color: #fff;
+ }
+ }
+ .ant-pagination-prev,
+ .ant-pagination-next {
+ .ant-pagination-item-link {
+ border: 1px solid #434343;
+ background-color: transparent;
+ color: #bfbfbf;
+
+ &:hover {
+ border-color: #1677ff;
+ color: #1677ff;
+ }
+ }
+ }
+ }
+}
body {
font-size: 1.6rem;
@@ -151,8 +199,6 @@ body {
background: var(--body-bg);
}
-
-
a {
color: inherit;
text-decoration: none;
@@ -166,6 +212,10 @@ li {
.icon {
filter: var(--icon-color);
display: block;
+
+ @include screen(sm) {
+ font-size: 1.4rem;
+ }
}
a,
@@ -188,7 +238,6 @@ textarea {
font-size: inherit;
}
-
.popover-language__list {
padding: 4px;
min-width: 146px;
@@ -272,7 +321,9 @@ textarea {
.ant-modal-content {
min-width: 600px;
margin: 16px 24px;
- font-family: Arial, -apple-system, BlinkMacSystemFont, Roboto, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
+ font-family: Arial, -apple-system, BlinkMacSystemFont, Roboto, "Segoe UI",
+ Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
+ "Segoe UI Symbol";
.ant-modal-body {
display: flex;
@@ -298,7 +349,9 @@ textarea {
.review-course-modal {
.ant-modal-content {
- font-family: Arial, -apple-system, BlinkMacSystemFont, Roboto, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
+ font-family: Arial, -apple-system, BlinkMacSystemFont, Roboto, "Segoe UI",
+ Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
+ "Segoe UI Symbol";
.ant-modal-body {
display: flex;
@@ -325,7 +378,6 @@ textarea {
.review-filter-left {
flex: 3;
-
.review-filter-left-item {
display: flex;
align-items: center;
@@ -355,10 +407,6 @@ textarea {
span {
text-align: center;
}
-
-
-
-
}
.review-cancel-filter {
@@ -369,12 +417,9 @@ textarea {
}
&.active {
- opacity: .25;
+ opacity: 0.25;
}
-
}
-
-
}
.review-filter-right {
@@ -383,8 +428,6 @@ textarea {
flex-direction: column;
width: 100%;
gap: 10px;
-
-
}
}
}
@@ -416,7 +459,6 @@ textarea {
align-items: flex-start;
gap: 5px;
-
.popover-carts-item-left {
flex: 3;
@@ -478,7 +520,6 @@ textarea {
}
}
-
.popover-carts.ant-popover {
.ant-popover-inner {
padding: 15px;
@@ -526,8 +567,6 @@ textarea {
width: 200px;
}
-
-
.popover-user-profile-top {
display: flex;
gap: 12px;
@@ -666,7 +705,6 @@ textarea {
width: 390px;
color: var(--text-color);
-
.popover-learning-header {
display: flex;
align-items: center;
@@ -717,7 +755,7 @@ textarea {
.popover-learning-course-title {
font-weight: 550;
- font-size: 1.4rem
+ font-size: 1.4rem;
}
.popover-learning-course-time {
@@ -755,7 +793,6 @@ textarea {
}
}
-
.popover-search-container {
font-family: inherit;
display: flex;
@@ -836,7 +873,7 @@ textarea {
background: var(--popover-bg);
border: 1px solid var(--popover-border);
box-shadow: var(--popover-shadow);
- width: var(--header-form-width)
+ width: var(--header-form-width);
}
.ant-popover-inner-content {
@@ -866,4 +903,4 @@ textarea {
border: 0;
padding: 0;
}
-}
\ No newline at end of file
+}