Skip to content

Commit

Permalink
Merge branch 'develop-client' into feature/CK-211
Browse files Browse the repository at this point in the history
  • Loading branch information
sh981013s authored Oct 1, 2023
2 parents 2087e02 + b60c3e3 commit 7ecacab
Show file tree
Hide file tree
Showing 29 changed files with 723 additions and 132 deletions.
26 changes: 4 additions & 22 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { lazy, PropsWithChildren, Suspense, useEffect } from 'react';
import { BrowserRouter, Route, Routes, useNavigate } from 'react-router-dom';
import { lazy, Suspense } from 'react';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import theme from '@styles/theme';
import GlobalStyle from '@styles/GlobalStyle';
import { ThemeProvider } from 'styled-components';
Expand All @@ -13,16 +13,14 @@ import RoadmapDetailPage from './pages/roadmapDetailPage/RoadmapDetailPage';
import RoadmapCreatePage from './pages/roadmapCreatePage/RoadmapCreatePage';
import ToastProvider from '@components/_common/toastProvider/ToastProvider';
import MyPage from '@pages/myPage/MyPage';
import UserInfoProvider, {
useUserInfoContext,
} from './components/_providers/UserInfoProvider';
import UserInfoProvider from './components/_providers/UserInfoProvider';
import RoadmapSearchResult from './components/roadmapListPage/roadmapSearch/RoadmapSearchResult';
import MainPage from '@pages/mainPage/MainPage';
import useToast from '@hooks/_common/useToast';
import OAuthRedirect from './components/loginPage/OAuthRedirect';
import AsyncBoundary from './components/_common/errorBoundary/AsyncBoundary';
import SessionHandler from '@components/_common/sessionHandler/SessionHandler';
import RouteChangeTracker from '@components/_common/routeChangeTracker/RouteChangeTracker';
import PrivateRouter from '@components/_common/privateRouter/PrivateRouter';

const GoalRoomDashboardPage = lazy(
() => import('@pages/goalRoomDashboardPage/GoalRoomDashboardPage')
Expand All @@ -32,22 +30,6 @@ const GoalRoomCreatePage = lazy(
() => import('@pages/goalRoomCreatePage/GoalRoomCreatePage')
);

const PrivateRouter = (props: PropsWithChildren) => {
const { children } = props;
const { userInfo } = useUserInfoContext();
const { triggerToast } = useToast();
const navigate = useNavigate();

useEffect(() => {
if (userInfo.id === null) {
navigate('/login');
triggerToast({ message: '로그인이 필요한 서비스입니다.' });
}
}, [userInfo.id, navigate]);

return <>{children}</>;
};

const App = () => {
return (
<ThemeProvider theme={theme}>
Expand Down
24 changes: 24 additions & 0 deletions client/src/components/_common/privateRouter/PrivateRouter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { PropsWithChildren, useEffect } from 'react';
import { useUserInfoContext } from '@components/_providers/UserInfoProvider';
import useToast from '@hooks/_common/useToast';
import { useNavigate } from 'react-router-dom';
import { getCookie } from '@utils/_common/cookies';

const PrivateRouter = (props: PropsWithChildren) => {
const { children } = props;
const { userInfo } = useUserInfoContext();
const { triggerToast } = useToast();
const navigate = useNavigate();
const accessToken = getCookie('access_token');

useEffect(() => {
if (userInfo.id === null && !accessToken) {
navigate('/login');
triggerToast({ message: '로그인이 필요한 서비스입니다.' });
}
}, [userInfo.id, navigate]);

return <>{children}</>;
};

export default PrivateRouter;
58 changes: 58 additions & 0 deletions client/src/components/_common/slider/Slider.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import media from '@styles/media';
import styled, { css } from 'styled-components';

export const Slider = styled.div`
position: relative;
overflow: hidden;
display: flex;
align-items: center;
width: 100%;
`;

export const Button = styled.button<{ isHovered: boolean }>`
position: absolute;
display: flex;
align-items: center;
justify-content: center;
width: 7rem;
height: 12rem;
background-color: rgba(1, 1, 1, 0.2);
border-radius: 8px;
box-shadow: ${({ theme }) => theme.shadows.box};
${({ isHovered }) =>
media.desktop(css`
opacity: ${isHovered ? 1 : 0};
transition: opacity 0.2s ease;
`)}
`;

export const PrevButton = styled(Button)<{ isFirstContentIndex: boolean }>`
left: 2rem;
display: ${({ isFirstContentIndex }) => isFirstContentIndex && 'none'};
`;

export const NextButton = styled(Button)<{ isLastContentIndex: boolean }>`
right: 2rem;
display: ${({ isLastContentIndex }) => isLastContentIndex && 'none'};
`;

export const Contents = styled.article<{ curIndex: number; length: number }>`
transform: ${({ curIndex }) => `translateX(${-curIndex * 100}%)`};
display: flex;
width: ${({ length }) => `${length * 100}%`};
transition: transform 0.3s ease;
`;

export const Content = styled.div`
flex-shrink: 0;
width: 100%;
& > * {
min-height: 12rem;
}
`;
43 changes: 43 additions & 0 deletions client/src/components/_common/slider/Slider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { PropsWithChildren } from 'react';
import * as S from './Slider.styles';
import useHover from '@hooks/_common/useHover';
import SVGIcon from '@components/icons/SVGIcon';
import useSlider from '@hooks/_common/useSlider';

const Slider = ({ children }: PropsWithChildren) => {
const {
curIndex,
slideToPrevContent,
slideToNextContent,
isFirstContentIndex,
isLastContentIndex,
childrenArray,
} = useSlider(children);
const { isHovered, handleMouseEnter, handleMouseLeave } = useHover();

return (
<S.Slider onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
<S.Contents curIndex={curIndex} length={childrenArray.length}>
{childrenArray.map((child, index) => (
<S.Content key={child?.props?.id || index}>{child}</S.Content>
))}
</S.Contents>
<S.PrevButton
onClick={slideToPrevContent}
isHovered={isHovered}
isFirstContentIndex={isFirstContentIndex}
>
<SVGIcon name='LeftIcon' />
</S.PrevButton>
<S.NextButton
onClick={slideToNextContent}
isHovered={isHovered}
isLastContentIndex={isLastContentIndex}
>
<SVGIcon name='RightIcon' />
</S.NextButton>
</S.Slider>
);
};

export default Slider;
49 changes: 49 additions & 0 deletions client/src/components/icons/svgIcons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2454,3 +2454,52 @@ export const ImageUploadIcon = ({ width, ...props }: SVGProps<SVGSVGElement>) =>
/>
</svg>
);

export const LeftIcon = ({ width, ...props }: SVGProps<SVGSVGElement>) => (
<svg
{...props}
xmlns='http://www.w3.org/2000/svg'
width={width}
height={width}
viewBox='0 0 24 24'
fill='none'
stroke='#000000'
strokeWidth='2'
strokeLinecap='round'
strokeLinejoin='round'
>
<path d='M15 18l-6-6 6-6' />
</svg>
);

export const RightIcon = ({ width, ...props }: SVGProps<SVGSVGElement>) => (
<svg
{...props}
xmlns='http://www.w3.org/2000/svg'
width={width}
height={width}
viewBox='0 0 24 24'
fill='none'
stroke='#000000'
strokeWidth='2'
strokeLinecap='round'
strokeLinejoin='round'
>
<path d='M9 18l6-6-6-6' />
</svg>
);

export const NoImageIcon = ({ width, ...props }: SVGProps<SVGSVGElement>) => (
<svg
{...props}
xmlns='http://www.w3.org/2000/svg'
width={width}
height={width}
viewBox='0 0 32 32'
>
<path
fill='currentColor'
d='M30 3.414L28.586 2L2 28.586L3.414 30l2-2H26a2.003 2.003 0 0 0 2-2V5.414zM26 26H7.414l7.793-7.793l2.379 2.379a2 2 0 0 0 2.828 0L22 19l4 3.997zm0-5.832l-2.586-2.586a2 2 0 0 0-2.828 0L19 19.168l-2.377-2.377L26 7.414zM6 22v-3l5-4.997l1.373 1.374l1.416-1.416l-1.375-1.375a2 2 0 0 0-2.828 0L6 16.172V6h16V4H6a2.002 2.002 0 0 0-2 2v16z'
/>
</svg>
);
45 changes: 25 additions & 20 deletions client/src/components/roadmapCreatePage/difficulty/Difficulty.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
/* eslint-disable react/no-unused-prop-types */
import { useSelect } from '@/hooks/_common/useSelect';
import { DifficultiesType, DifficultyKeyType } from '@/myTypes/roadmap/internal';
import { getInvariantObjectKeys, invariantOf } from '@/utils/_common/invariantType';
import { useEffect } from 'react';
import { Select, SelectBox } from '../selector/SelectBox';
import * as S from './difficulty.styles';

// 임시 더미데이터
export type DummyDifficultyType = {
[key: number]: string;
const Difficulties: DifficultiesType = {
VERY_EASY: '매우쉬움',
EASY: '쉬움',
NORMAL: '보통',
DIFFICULT: '어려움',
VERY_DIFFICULT: '매우어려움',
};

const DummyDifficulty: DummyDifficultyType = {
1: '매우쉬움',
2: '쉬움',
3: '보통',
4: '어려움',
5: '매우어려움',
type DifficultyProps = {
getSelectedDifficulty: (difficulty: DifficultyKeyType | null) => void;
};

type DifficultyType = {
getSelectedDifficulty: (difficulty: keyof DummyDifficultyType | null) => void;
};

const Difficulty = ({ getSelectedDifficulty }: DifficultyType) => {
const Difficulty = ({ getSelectedDifficulty }: DifficultyProps) => {
const { selectOption, selectedOption } = useSelect<number>();

useEffect(() => {
getSelectedDifficulty(selectedOption);
if (selectedOption === null) return;

getSelectedDifficulty(
getInvariantObjectKeys(invariantOf(Difficulties))[selectedOption]
);
}, [selectedOption]);

return (
Expand All @@ -46,7 +47,11 @@ const Difficulty = ({ getSelectedDifficulty }: DifficultyType) => {
{({ selectedId }: { selectedId: number | null }) => {
return (
<S.DifficultyValue>
{selectedId === null ? '선택안함' : DummyDifficulty[selectedId]}
{selectedId === null
? '선택안함'
: Difficulties[
getInvariantObjectKeys(invariantOf(Difficulties))[selectedId]
]}
</S.DifficultyValue>
);
}}
Expand All @@ -55,14 +60,14 @@ const Difficulty = ({ getSelectedDifficulty }: DifficultyType) => {
</Select.Trigger>
<Select.OptionGroup asChild>
<S.Wrapper>
{Object.keys(DummyDifficulty).map((difficultyId) => {
{getInvariantObjectKeys(invariantOf(Difficulties)).map((difficulty, idx) => {
return (
<Select.Option id={Number(difficultyId)} asChild>
<Select.Option id={idx} asChild>
<S.DifficultyOption>
<Select.Indicator id={Number(difficultyId)} asChild>
<Select.Indicator id={idx} asChild>
<S.OptionIndicator />
</Select.Indicator>
{DummyDifficulty[Number(difficultyId)]}
{Difficulties[difficulty]}
</S.DifficultyOption>
</Select.Option>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ const RoadmapCreateForm = () => {
<Period />
<Roadmap>
<>
{roadmapValue.roadmapNodes.length === 0 && (
<RoadmapItem
roadmapNumber={1}
itemId={0}
getRoadmapItemTitle={getRoadmapItemTitle}
getNodeImage={getNodeImage}
/>
)}
{roadmapValue.roadmapNodes.map((_, index) => {
return (
<RoadmapItem
Expand Down
17 changes: 13 additions & 4 deletions client/src/components/roadmapCreatePage/tag/Tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@ type TagProps = {
getTags: (tags: string[]) => void;
};
const Tag = ({ getTags }: TagProps) => {
const { tags, ref, addTagByButton, addTagByEnter, checkIsTagCountMax, deleteTag } =
useCreateTag();
const {
tags,
ref,
addTagByButton,
addTagByEnter,
checkIsTagCountMax,
checkIsAddCountMax,
deleteTag,
} = useCreateTag();

useEffect(() => {
getTags(tags);
Expand All @@ -29,8 +36,10 @@ const Tag = ({ getTags }: TagProps) => {
</S.DeleteButton>
</>
))}
<TagItem ref={ref} addTagByEnter={addTagByEnter} placeholder='# 태그명' />
{checkIsTagCountMax() && <S.AddButton onClick={addTagByButton}>+</S.AddButton>}
{checkIsTagCountMax() && (
<TagItem ref={ref} addTagByEnter={addTagByEnter} placeholder='# 태그명' />
)}
{checkIsAddCountMax() && <S.AddButton onClick={addTagByButton}>+</S.AddButton>}
</S.TagWrapper>
</S.Container>
);
Expand Down
Loading

0 comments on commit 7ecacab

Please sign in to comment.