Skip to content
7 changes: 2 additions & 5 deletions src/components/commons/Image/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import styles from "./Image.module.scss";
import { ImageInfo } from "@/type/type";
import classNames from "classnames/bind";
import styles from "./Image.module.scss";

const cx = classNames.bind(styles);

type ImageInfo = {
src: string;
alt: string;
};
type ObjectFit = "fill" | "contain" | "cover" | "scale-down" | "none";

interface ImageProps {
Expand Down
15 changes: 15 additions & 0 deletions src/components/domains/myPage/contents/Level/Level.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.level {
padding-bottom: 10rem;

@include responsive("T") {
padding-bottom: 8rem;
}

&__level {
padding-bottom: 4.8rem;

&-info {
padding-bottom: 2.4rem;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.progress-bar {
&__track {
width: 100%;
height: 1rem;
background-color: $gray20;
border-radius: 0.5rem;

@include responsive("M") {
height: 0.8rem;
}

&-fill {
background: linear-gradient(90deg, $primary30, $primary50);
border-radius: 0.5rem;
height: 100%;
animation: fill-up 0.8s linear forwards;
}

.beginner {
--target-width: 20%;
}

.intermediate {
--target-width: 60%;
}

.expert {
--target-width: 100%;
}
}

&__labels {
@include flexbox(between, center);
padding-top: 1rem;

@include responsive("M") {
padding-top: 0.5rem;
}

&-el {
@include text-style(1.6, 500, $black30);

@include responsive("M") {
font-size: 1.4rem;
}
}
}
}

@keyframes fill-up {
from {
width: 0%;
}
to {
width: var(--target-width, 100%);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import Image from "@/components/commons/Image";
import { IMAGES } from "@/constants/images";
import { authState } from "@/recoil/authAtom";
import classNames from "classnames/bind";
import { useRecoilState } from "recoil";
import styles from "./LevelProgressBar.module.scss";

const cx = classNames.bind(styles);

const LevelProgressBar = () => {
const [auth] = useRecoilState(authState);

if (!auth) {
return (
<div>
<p>사용자 정보를 불러올 수 없습니다.</p>
<Image imageInfo={IMAGES.courseMakerLogoMobile} />
</div>
);
}

return (
<div className={cx("progress-bar")}>
<div className={cx("progress-bar__track")}>
<div
className={cx(
"progress-bar__track-fill",
{ beginner: auth.role === "초보 여행가" },
{ intermediate: auth.role === "중급 여행가" },
{ expert: auth.role === "프로 여행가" },
)}></div>
</div>
<div className={cx("progress-bar__labels")}>
<span className={cx("progress-bar__labels-el")}>초보여행가</span>
<span className={cx("progress-bar__labels-el")}>중급여행가</span>
<span className={cx("progress-bar__labels-el")}>프로여행가</span>
</div>
</div>
);
};
export default LevelProgressBar;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.badge {
@include column-flexbox();
gap: 1rem;

&__img {
border-radius: 2rem;
height: 8rem;
background-color: $gray20; // fix: temp

@include responsive("M") {
}
}

&__description {
@include column-flexbox();

&-title {
@include text-style(1.8, 700, $black30);
}

&-criteria {
@include text-style(1.4, 500, $black30);
word-break: keep-all;
text-align: center;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Image from "@/components/commons/Image";

import classNames from "classnames/bind";
import styles from "./Badge.module.scss";

const cx = classNames.bind(styles);

interface BadgeProps {
img: string;
title: string;
criteria: string;
}

const Badge = ({ img, title, criteria }: BadgeProps) => {
return (
<figure className={cx("badge")}>
<div className={cx("badge__img")}>
<Image imageInfo={{ src: img, alt: `${title} 뱃지 이미지` }} />
</div>
<figcaption className={cx("badge__description")}>
<h4 className={cx("badge__description-title")}>{title}</h4>
<p className={cx("badge__description-criteria")}>{criteria}</p>
</figcaption>
</figure>
);
};
export default Badge;
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.my-badge {
&__title {
@include text-style(2.6, 700, $black30);
padding-bottom: 3.2rem;

@include responsive("M") {
font-size: 2.4rem;
padding-bottom: 2.4rem;
}
}

&__list {
display: grid;
grid-template-columns: repeat(4, 8rem);
justify-content: space-between;
row-gap: 2rem;

@include responsive("M") {
grid-template-columns: repeat(3, 8rem);
}
}
}
34 changes: 34 additions & 0 deletions src/components/domains/myPage/contents/Level/MyBadge/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import tempImg from "@/assets/images/child.svg";
import Badge from "./Badge";

import classNames from "classnames/bind";
import styles from "./MyBadge.module.scss";

const cx = classNames.bind(styles);

const mockData = [
{ id: 1, img: tempImg, title: "여행입문자", criteria: "첫 여행지를 작성한 여행가" },
{ id: 2, img: tempImg, title: "여행입문자", criteria: "여행지를 n개 이상 작성한 여행가" },
{ id: 3, img: tempImg, title: "여행입문자", criteria: "첫 여행지를 작성한 여행가" },
{ id: 5, img: tempImg, title: "여행입문자", criteria: "첫 여행지를 작성한 여행가" },
{ id: 6, img: tempImg, title: "여행입문자", criteria: "첫 여행지를 작성한 여행가" },
{ id: 4, img: tempImg, title: "여행입문자", criteria: "첫 여행지를 작성한 여행가" },
{ id: 7, img: tempImg, title: "여행입문자", criteria: "첫 여행지를 작성한 여행가" },
{ id: 8, img: tempImg, title: "여행입문자", criteria: "첫 여행지를 작성한 여행가" },
];

const MyBadge = () => {
return (
<div className={cx("my-badge")}>
<h2 className={cx("my-badge__title")}>내 뱃지</h2>
<ul className={cx("my-badge__list")}>
{mockData.map(({ id, img, title, criteria }) => (
<li key={id}>
<Badge img={img} title={title} criteria={criteria} />
</li>
))}
</ul>
</div>
);
};
export default MyBadge;
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
.all-level-info-modal {
@include column-flexbox();
gap: 0.32rem;
background-color: white;
border-radius: 1rem;
width: 64rem;
padding: 2.4rem;

@include responsive("M") {
width: calc(100% - 4rem);
padding: 2rem;
}

&__close-btn {
align-self: flex-end;
width: 2.4rem;
height: 2.4rem;
cursor: pointer;

@include responsive("M") {
width: 2rem;
height: 2rem;
}
}

&__header {
@include flexbox();

&-logo {
width: 8.4rem;

@include responsive("M") {
width: 6rem;
}
}

&-title {
@include text-style(1.6, 700, $black30);
text-align: center;

@include responsive("M") {
font-size: 1.2rem;
}
}
}

&__level-info-list {
&-element:not(:last-child) {
border-bottom: 0.1rem solid $gray20;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
.level-info-box {
display: grid;
grid-template-areas:
"level requirement"
". description";
justify-content: start;
align-items: center;
padding: 3rem 0;
gap: 1rem 1.4rem;

@include responsive("M") {
padding: 2.4rem 0;
gap: 0.8rem 1rem;
}

&__level {
@include flexbox();
gap: 0.7rem;
grid-area: level;

@include responsive("M") {
gap: 0.4rem;
}

&-img {
grid-area: img;
width: 4rem;
height: 4rem;
border-radius: 50%;
box-shadow: 0px 3px 16px 0px rgba(0, 0, 0, 0.08);
overflow: hidden;

@include responsive("M") {
width: 3.6rem;
height: 3.6rem;
}
}

&-name {
@include text-style(1.4, 700, $black30);

@include responsive("M") {
font-size: 1.2rem;
}
}
}

&__requirement {
@include text-style(1.4, 600, $black30);
grid-area: requirement;

@include responsive("M") {
font-size: 1.2rem;
}

&-additionalInfo {
@include text-style(1.1, 500, $black30);
display: block;

@include responsive("M") {
font-size: 1rem;
}
}
}

&__description {
@include text-style(1.3, 500, $black30);
grid-area: description;

@include responsive("M") {
font-size: 1.2rem;
}

&-additionalInfo {
@include text-style(1.1, 500, $black30);
display: block;

@include responsive("M") {
font-size: 1rem;
}
}
}
}
Loading
Loading