Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: 리뷰 작성 페이지 추가, 리뷰 메인 페이지 리스트 디자인 수정 #120

Merged
merged 6 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions public/icons/starIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/icons/starIconGray.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/ai.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/back.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/data.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/front.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
146 changes: 142 additions & 4 deletions src/pages/campReviewList/components/BootcampList.module.scss
Original file line number Diff line number Diff line change
@@ -1,13 +1,151 @@
@use '@/styles/abstracts/variables' as m;
@use '@/styles/abstracts/variables' as v;
@use '@/styles/abstracts/mixins' as m;

// 스타일 1
.Container {
display: flex;
justify-content: center;
align-items: center;
}

.listWrapContainer {
margin-top: 2rem;
margin: 2rem;

display: grid;
grid-template-columns: repeat(2, 300px);
grid-gap: 20px;

@include m.mobile {
grid-template-columns: repeat(1, 300px);
}
}

.listContainer {
margin-top: 1rem;

padding: 1rem;

border: 1px solid;
border-radius: 1rem;
border: 1px solid v.$extra-light-gray;
box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
}

.listContainer:hover {
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
}

.listContainer img {
width: 100%;
height: 100%;

display: block;

object-fit: cover;
background-position: center;
background-repeat: no-repeat;
}
.imgWrapper {
position: relative;
width: 100%;
height: 230px;

border-radius: 1rem;

overflow: hidden;
}

.imgWrapper::after {
position: absolute;
top: 0;
left: 0;
content: '';
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
}
.imgTextBox {
position: absolute;
top: 50%;
left: 50%;

transform: translate(-50%, -50%);

font-weight: v.$font-medium;
font-size: v.$text-xl;
text-align: center;
color: v.$white;

z-index: 10;
}

.title {
display: flex;
justify-content: space-between;
align-items: center;

font-size: v.$text-lg;
font-weight: v.$font-medium;

margin: 0.5rem 0;
}
.title > div:nth-of-type(2) {
font-size: v.$text-sm;
font-weight: v.$font-regular;
}

// 스타일 2
// .listContainer {
// margin-top: 1rem;
// padding: 1.5rem;

// border-radius: 1rem;
// border: 1px solid v.$extra-light-gray;
// box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
// }

// .listContainer:hover {
// box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
// }

// .title {
// font-size: v.$text-xl;

// @include m.mobile {
// text-align: center;
// }
// }

// .description {
// display: flex;
// align-items: center;

// padding-top: 1rem;

// @include m.mobile {
// justify-content: center;
// flex-direction: column;
// }
// }

// .rating {
// font-size: v.$text-lg;
// font-weight: v.$font-medium;

// margin-right: 1.5rem;

// @include m.mobile {
// margin-right: 0;
// padding: 0.3rem;
// }
// }

// .totalReviews {
// font-size: v.$text-md;
// color: v.$gray;

// margin-right: 1.5rem;

// @include m.mobile {
// margin-right: 0;
// padding: 0.3rem;
// }
// }
67 changes: 54 additions & 13 deletions src/pages/campReviewList/components/BootcampList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,62 @@ import styles from './BootcampList.module.scss';
import Button from '@/components/atoms/button/Button';

const BootcampList = () => {
const list = ['42 Seoul', '우아한테크코스', '패스트캠퍼스'];
const list = [
{
bootcamp: '42 Seoul',
averageRating: 4.2,
totalReviews: 20,
},
{
bootcamp: '우아한테크코스',
averageRating: 4.0,
totalReviews: 100,
},
{
bootcamp: '패스트캠퍼스',
averageRating: 1.2,
totalReviews: 1,
},
];

const selectRandomImage = () => {
const images = ['/images/ai.png', '/images/back.png', '/images/front.png'];

const randomIndex = Math.floor(Math.random() * images.length);

return images[randomIndex];
};

return (
<ul className={styles.listWrapContainer}>
{list.map((v, i) => {
return (
<li key={i} className={styles.listContainer}>
<div>{v}</div>
<div>평점..</div>
<div>리뷰 요약..</div>
<Button variant="primary">자세히 보기</Button>
</li>
);
})}
</ul>
<div className={styles.Container}>
<ul className={styles.listWrapContainer}>
{list.map((bootcamp, index) => {
return (
<li key={index} className={styles.listContainer}>
<div className={styles.imgWrapper}>
<div className={styles.imgTextBox}>{bootcamp.bootcamp}</div>
<img src={selectRandomImage()} />
</div>
<div className={styles.title}>
<div>⭐ {bootcamp.averageRating.toFixed(1)}</div>
<div>총 리뷰: {bootcamp.totalReviews}개</div>
</div>
<Button variant="primary">리뷰 상세 보기</Button>
</li>
// <li key={index} className={styles.listContainer}>
// <div className={styles.title}>
// <div>{bootcamp.bootcamp}</div>
// </div>
// <div className={styles.description}>
// <div className={styles.rating}>⭐ {bootcamp.averageRating.toFixed(1)}</div>
// <div className={styles.totalReviews}>리뷰 {bootcamp.totalReviews}개</div>
// <Button variant="primary">리뷰 상세 보기</Button>
// </div>
// </li>
);
})}
</ul>
</div>
);
};

Expand Down
8 changes: 6 additions & 2 deletions src/pages/campReviewList/components/ReviewMenus.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import Button from '@/components/atoms/button/Button';
import { Link } from 'react-router-dom';
import styles from './ReviewMenus.module.scss';

import { ReactComponent as PenSquare } from '@/assets/icons/pen_square.svg';

const ReviewMenus = () => {
return (
<Button variant="primary">
<PenSquare />
<span>리뷰 작성하기</span>
<Link className={styles.link} to={'/review/write'}>
<PenSquare />
<span>리뷰 작성하기</span>
</Link>
</Button>
);
};
Expand Down
19 changes: 19 additions & 0 deletions src/pages/writeReview/components/ReviewTag.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@use '@/styles/abstracts/variables' as v;

.tagContainer {
display: flex;
align-items: center;

width: 200px;

border-radius: 0.3rem;

font-size: v.$text-sm;

padding: 0.4rem;
margin: 0.4rem;
}

.grow {
flex-grow: 1;
}
58 changes: 58 additions & 0 deletions src/pages/writeReview/components/ReviewTag.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useState } from 'react';
import styles from './ReviewTag.module.scss';
import { useSetRecoilState } from 'recoil';
import { reviewFormState } from '@/recoil/reviewFormState';

interface Props {
icon: string;
text: string;
type: string;
id: number;
}

const ReviewTag = ({ icon, text, type, id }: Props) => {
const setReview = useSetRecoilState(reviewFormState);
const [isClicked, setIsClicked] = useState(false);

const getBackground = () => {
if (type === 'good') {
return isClicked ? '#ffa0a08e' : '#ffc3c349';
} else {
return isClicked ? '#9b9bffc2' : '#b7b7fd67';
}
};

const handleClick = () => {
setIsClicked((prev) => !prev);
setReview((prev) => {
if (type === 'good') {
return {
...prev,
goodTags: isClicked
? prev.goodTags.filter((tagId) => tagId !== id)
: [...prev.goodTags, id],
};
} else {
return {
...prev,
badTags: isClicked ? prev.badTags.filter((tagId) => tagId !== id) : [...prev.badTags, id],
};
}
});
};

return (
<button
className={styles.tagContainer}
style={{ backgroundColor: getBackground() }}
onClick={handleClick}
>
<div>{icon}</div>
<div>{text}</div>
<div className={styles.grow}></div>
{isClicked && <div>✅</div>}
</button>
);
};

export default ReviewTag;
22 changes: 22 additions & 0 deletions src/pages/writeReview/components/SelectTag.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@use '@/styles/abstracts/variables' as v;

.title {
// font-size: v.$text-sm;

margin: 1rem 0.4rem 0 0.4rem;
font-weight: v.$font-medium;
}

.tagList {
display: flex;

flex-wrap: wrap;
}

.tagListContainer {
margin-bottom: 1rem;
}

.ListTitle {
margin: 0 0.4rem;
}
Loading
Loading