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[#245]: 랜딩 페이지 SSR 적용 및 클랜 모집 슬라이더 배너 구현 #249

Merged
merged 10 commits into from
Mar 31, 2024
Merged
Binary file added public/pngs/clan-background.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/pngs/slider-battlegrounds.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/pngs/slider-lol.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/pngs/slider-minecraft.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/pngs/slider-overwatch.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/pngs/slider-stroke-active.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/pngs/slider-stroke-default.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/components/commons/Tag/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import classNames from 'classnames/bind';

import { formatPostTypeToKR } from '@/utils';

import { ReservedPostTypesEN } from '@/types';
import { PostTypesEN } from '@/types';

import styles from './Tag.module.scss';

const cx = classNames.bind(styles);

type TagProps = {
postType: ReservedPostTypesEN | string;
postType: PostTypesEN | string;
};

const Tag = ({ postType }: TagProps) => {
Expand Down
15 changes: 15 additions & 0 deletions src/components/commons/buttons/SliderButton.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
%arrow-btn-base {
@include flexbox;

width: 4rem;
height: 4rem;

background: $opacity-white-10;
backdrop-filter: $slider-button-blur;
border: 0.1rem solid $opacity-white-20;
border-radius: 0.4rem;
}

.clan-slider-btn {
@extend %arrow-btn-base;
}
28 changes: 28 additions & 0 deletions src/components/commons/buttons/SliderButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Image from 'next/image';

import classNames from 'classnames/bind';

import { SVGS } from '@/constants';

import styles from './SliderButton.module.scss';

const cx = classNames.bind(styles);

type SliderButtonProps = {
type: 'left' | 'right';
onClick: () => void;
};

const SliderButton = ({ type, onClick }: SliderButtonProps) => {
const { active } = type === 'left' ? SVGS.arrow.left : SVGS.arrow.right;

return (
<div className={cx('lg-only')}>
<button className={cx('clan-slider-btn', `btn-${type}`)} onClick={onClick}>
<Image src={active.url} alt={active.alt} width={20} height={20} />
</button>
</div>
);
};

export default SliderButton;
66 changes: 66 additions & 0 deletions src/components/landing/ClanCard.tsx/ClanCard.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
.slider-banner-item {
&-content {
@include responsive(PC) {
&:hover {
background-image: url('/pngs/slider-stroke-active.png');
box-shadow: $clan-card-shadow;
}

&:hover .slider-banner-item-info-title {
color: $white;
}
}

@include responsive(T) {
background-image: url('/pngs/slider-stroke-active.png');
}

cursor: pointer;

position: relative;

display: block;

width: 100%;
height: 100%;

background: url('/pngs/slider-stroke-default.png') no-repeat center/cover;

transition: $base-transition;
}

&-tag {
position: absolute;
top: 1.2rem;
left: 1.2rem;
}

&-info {
position: absolute;
bottom: 0;
left: 0;

overflow: hidden;

width: 100%;
padding: 2.4rem;

&-title {
@include responsive(T) {
color: $white;
}

@include text-style(24, $gray30, bold);

overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
transition: $base-transition;
}

&-createdAt {
@include flexbox(start, center, 0.4rem);
@include text-style(14, $gray10);
}
}
}
41 changes: 41 additions & 0 deletions src/components/landing/ClanCard.tsx/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import Image from 'next/image';
import Link from 'next/link';

import classNames from 'classnames/bind';

import { SVGS } from '@/constants';
import { getFormatDate } from '@/utils';

import Tag from '@/components/commons/Tag';

import styles from './ClanCard.module.scss';

const cx = classNames.bind(styles);

const { url, alt } = SVGS.calendar.active;

export type ClanCardProps = {
id: number;
gameName: string;
clanTitle: string;
createdAt: string;
};

const ClanCard = ({ id, gameName, clanTitle, createdAt }: ClanCardProps) => {
return (
<Link href={`/${gameName}/${id}`} className={cx('slider-banner-item-content')}>
<div className={cx('slider-banner-item-tag')}>
<Tag postType='clan-recruitment' />
</div>
<div className={cx('slider-banner-item-info')}>
<h3 className={cx('slider-banner-item-info-title')}>{clanTitle}</h3>
<div className={cx('slider-banner-item-info-createdAt')}>
<Image src={url} alt={alt} width={20} height={20} />
<span>{getFormatDate(createdAt)}</span>
</div>
</div>
</Link>
);
};

export default ClanCard;
159 changes: 159 additions & 0 deletions src/components/landing/ClanRecruitment/ClanRecruitment.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
$slider-item-margin: 2.4rem;
$slider-banner-tablet: 389.5rem;
$slider-banner-mobile: 387.9rem;

.clan {
@include responsive(T) {
height: 80rem;
}

width: 100%;
height: 100vh;
background: url('/pngs/clan-background.png') no-repeat center/cover;

.container {
@include responsive(T) {
max-width: 100%;
padding-top: 10.2rem;
}

@include responsive(M) {
max-width: 100%;
padding-top: 8.8rem;
}

max-width: 120rem;
height: 100%;
margin: 0 auto;
padding-top: 14.4rem;
}

&-header {
@include column-flexbox($gap: 1.6rem);

@include responsive(M) {
margin-bottom: 3.2rem;
}

margin-bottom: 4.8rem;

&-title {
@include text-style-quantico(40, $purple);

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

&-description {
@include text-style(24, $gray30);

@include responsive(M) {
font-size: 1.6rem;
line-height: 2.4rem;
}

max-width: 64rem;
text-align: center;

&-highlight {
color: $white;
}
}
}

&-slider {
position: relative;

&-btn-prev,
&-btn-next {
@include pos-center-y;

z-index: $slider-button-level;
}

&-btn-prev {
left: -2rem;
}

&-btn-next {
right: -2rem;
}

.slider-banner {
@include responsive(T) {
@include no-scrollbar;

overflow-x: scroll;
padding-left: 4rem;
}

@include responsive(M) {
padding-left: 1.5rem;
}

scroll-behavior: smooth;

overflow: hidden;

width: 100%;
height: 100%;
padding-top: 1.6rem;

&-list {
@include responsive(T) {
width: $slider-banner-tablet;
}

@include responsive(M) {
width: $slider-banner-mobile;
}

width: calc(400vw + ($slider-item-margin * 11));
}

&-item {
@include responsive(T) {
width: 30rem;
height: 36rem;
margin-right: 4rem;
}

@include responsive(T) {
margin-right: 1.5rem;
}

@include responsive(PC) {
&:hover {
transform: translateY(-1.6rem);
}
}

display: inline-block;
width: 38.4rem;
height: 46rem;
transition: $base-transition;

&.league-of-legends {
background: url('/pngs/slider-lol.png') no-repeat center/cover;
}

&.battlegrounds {
background: url('/pngs/slider-battlegrounds.png') no-repeat center/cover;
}

&.overwatch-2 {
background: url('/pngs/slider-overwatch.png') no-repeat center/cover;
}

&.minecraft {
background: url('/pngs/slider-minecraft.png') no-repeat center/cover;
}

&:not(:last-child) {
margin-right: 2.4rem;
}
}
}
}
}
Loading