Skip to content
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
Binary file modified public/assets/android-chrome-192x192.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 modified public/assets/android-chrome-512x512.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 modified public/assets/favicon-16x16.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 modified public/assets/favicon-32x32.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 modified public/assets/intro-1.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 modified public/assets/intro-2.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 modified public/assets/intro-3.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 modified public/assets/logos/og-image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/components/atoms/DraggableContainer/index.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.container {
overflow-x: scroll;
cursor: grab;
user-select: none;

&:active {
cursor: grabbing;
}
}
54 changes: 54 additions & 0 deletions src/components/atoms/DraggableContainer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use client';

import { ComponentProps } from 'react';

import clsx from 'clsx';

import useDraggableScroll from '@/hook/useDraggableScroll';

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

type DraggableContainerProps = ComponentProps<'div'> & {
className?: string;
ariaLabel?: string;
};

function DraggableContainer({
children,
className,
ariaLabel,
...props
}: DraggableContainerProps) {
const {
ref,
onMouseDown,
onMouseLeave,
onMouseUp,
onMouseMove,
onTouchStart,
onTouchMove,
onTouchEnd,
} = useDraggableScroll();

return (
<div
ref={ref}
role="region"
aria-label={ariaLabel}
tabIndex={0}
className={clsx(styles.container, className)}
onMouseDown={onMouseDown}
onMouseLeave={onMouseLeave}
onMouseUp={onMouseUp}
onMouseMove={onMouseMove}
onTouchStart={onTouchStart}
onTouchMove={onTouchMove}
onTouchEnd={onTouchEnd}
{...props}
>
{children}
</div>
);
}

export default DraggableContainer;
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@

&.primary {
background-color: var(--primary);

&:hover {
background-color: var(--primary-hover);
}
}

@include mobile {
Expand Down
1 change: 0 additions & 1 deletion src/components/pages/Recruit/index.module.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
.cardListWrapper {
overflow-x: scroll;
width: 100%;

.cardList {
Expand Down
9 changes: 4 additions & 5 deletions src/components/pages/Recruit/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Flex } from '@sipe-team/side';

import ContentWithTitle from '@/components/atoms/ContentWithTitle';
import DraggableContainer from '@/components/atoms/DraggableContainer';
import Layout from '@/components/atoms/Layout';
import Table from '@/components/molecules/Table';
import Faq from '@/components/organisms/Faq';
Expand All @@ -19,11 +20,9 @@ function Recruit() {
<Table dataList={Applicants} isApplicant={true} />
</ContentWithTitle>
<ContentWithTitle title="모집 일정">
<Flex
align="center"
<DraggableContainer
ariaLabel="모집 일정 스크롤 영역"
className={styles.cardListWrapper}
justify="flex-start"
wrap="wrap"
>
<Flex
align="center"
Expand All @@ -43,7 +42,7 @@ function Recruit() {
/>
))}
</Flex>
</Flex>
</DraggableContainer>
</ContentWithTitle>
<ContentWithTitle title="활동안내">
<Table dataList={InActivity} isApplicant={false} />
Expand Down
79 changes: 79 additions & 0 deletions src/hook/useDraggableScroll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { useCallback, useRef } from 'react';

interface UseDraggableScrollReturn {
ref: React.RefObject<HTMLDivElement>;
onMouseDown: (e: React.MouseEvent) => void;
onMouseLeave: () => void;
onMouseUp: () => void;
onMouseMove: (e: React.MouseEvent) => void;
onTouchStart: (e: React.TouchEvent) => void;
onTouchMove: (e: React.TouchEvent) => void;
onTouchEnd: () => void;
}

export default function useDraggableScroll(): UseDraggableScrollReturn {
const ref = useRef<HTMLDivElement>(null);
const isDragging = useRef(false);
const startX = useRef(0);
const scrollLeft = useRef(0);

const onMouseDown = useCallback((e: React.MouseEvent) => {
if (!ref.current) return;
isDragging.current = true;
startX.current = e.pageX - ref.current.offsetLeft;
scrollLeft.current = ref.current.scrollLeft;
ref.current.style.cursor = 'grabbing';
}, []);

const onMouseLeave = useCallback(() => {
isDragging.current = false;
if (ref.current) {
ref.current.style.cursor = 'grab';
}
}, []);

const onMouseUp = useCallback(() => {
isDragging.current = false;
if (ref.current) {
ref.current.style.cursor = 'grab';
}
}, []);

const onMouseMove = useCallback((e: React.MouseEvent) => {
if (!isDragging.current || !ref.current) return;
e.preventDefault();
const x = e.pageX - ref.current.offsetLeft;
const walk = (x - startX.current) * 2;
ref.current.scrollLeft = scrollLeft.current - walk;
}, []);

const onTouchStart = useCallback((e: React.TouchEvent) => {
if (!ref.current) return;
isDragging.current = true;
startX.current = e.touches[0].pageX - ref.current.offsetLeft;
scrollLeft.current = ref.current.scrollLeft;
}, []);

const onTouchMove = useCallback((e: React.TouchEvent) => {
if (!isDragging.current || !ref.current) return;
e.preventDefault();
const x = e.touches[0].pageX - ref.current.offsetLeft;
const walk = (x - startX.current) * 2;
ref.current.scrollLeft = scrollLeft.current - walk;
}, []);

const onTouchEnd = useCallback(() => {
isDragging.current = false;
}, []);

return {
ref,
onMouseDown,
onMouseLeave,
onMouseUp,
onMouseMove,
onTouchStart,
onTouchMove,
onTouchEnd,
};
}
51 changes: 31 additions & 20 deletions src/libs/constants/recruit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ export const JOIN_FORM_URL = 'https://forms.gle/SPM3xXTVrnvupcLDA';
export const JOIN_ALARM_FORM_URL = 'https://forms.gle/VS7Ap4xfSyf2qYqQ6';
export const JOIN_NEXT_ALARM_FORM_URL = 'https://forms.gle/VS7Ap4xfSyf2qYqQ6';

export type CardListType = {
title: string;
processDate: string;
subTitle: string;
};

export const Applicants = [
{
text: '격주 토요일 오후 2시 ~ 6시에 진행되는 정규 활동에 성실하게 참여할 수 있는',
Expand All @@ -22,53 +28,58 @@ export const Applicants = [

export const InActivity = [
{
recurring_date: '1회차 (04.26)',
recurring_date: '1회차 (03.07)',
text: 'OT',
badge: '',
},
{
recurring_date: '2회차 (05.10)',
recurring_date: '2회차 (03.21)',
text: 'MT',
badge: '1차 미션 시작',
badge: '1차 미션 팀 빌딩',
},
{
recurring_date: '3회차 (05.24)',
text: '사이프챗',
recurring_date: '3회차 (04.04)',
text: '라이트닝 토크 1',
badge: '',
},
{
recurring_date: '4회차 (06.07)',
text: '홈커밍데이',
recurring_date: '4회차 (04.18)',
text: '개발자 힐링 캠프',
badge: '',
},
{
recurring_date: '5회차 (06.21)',
recurring_date: '5회차 (05.02)',
text: '1차 미션 발표',
badge: '',
},
{
recurring_date: '6회차 (07.05)',
recurring_date: '6회차 (05.16)',
text: '스파크 세션',
badge: '2차 미션 시작',
badge: '해커톤 팀 빌딩',
},
{
recurring_date: '7회차 (07.19)',
text: '사이데이션',
recurring_date: '7회차 (05.30)',
text: '내친소',
badge: '',
},
{
recurring_date: '8회차 (08.02)',
text: '사담콘',
recurring_date: '8회차 (06.13)',
text: '라이트닝 토크 2',
badge: '',
},
{
recurring_date: '9회차 (06.27)',
text: '사이프톤',
badge: '',
},
{
recurring_date: '9회차 (08.16)',
text: '2차 미션 발표',
recurring_date: '10회차 (07.11)',
text: '사담콘',
badge: '',
},
{
recurring_date: '10회차 (08.30)',
text: '사이프-로그',
recurring_date: '10회차 (07.25)',
text: '사이프 로그',
badge: '정규 활동 종료',
},
];
Expand All @@ -82,7 +93,7 @@ export const CardList = [
{
title: '서류 합격자 발표',
processDate: '01.13(화)',
subTitle: '오후 1시 예정',
subTitle: '힙격자 개별 연락',
},
{
title: '오프라인 인터뷰',
Expand All @@ -93,7 +104,7 @@ export const CardList = [
{
title: '최종 합격자 발표',
processDate: '02.14(토)',
subTitle: '오후 1시 예정',
subTitle: '힙격자 개별 연락',
},
{
title: '정규 활동 시작',
Expand Down
1 change: 1 addition & 0 deletions src/styles/variables.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
:root {
/* colors */
--primary: #ffb24d;
--primary-hover: #d9963f;
// --primary: #00ffff;
--black: #131518;
--gray000: #1a202c;
Expand Down