Skip to content

Commit

Permalink
Merge pull request #103 from SWYP-InNOut/fix/bug
Browse files Browse the repository at this point in the history
Fix/bug
  • Loading branch information
ssilver01 authored Aug 7, 2024
2 parents e5770d0 + b004e95 commit 85022b0
Show file tree
Hide file tree
Showing 10 changed files with 178 additions and 94 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
"@tanstack/react-query-devtools": "^5.49.2",
"axios": "^1.7.2",
"eslint-config-prettier": "^9.1.0",
"framer-motion": "^11.3.22",
"js-cookie": "^3.0.5",
"lottie-web": "^5.12.2",
"popmotion": "^11.0.5",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.52.1",
Expand Down
1 change: 1 addition & 0 deletions public/Ball_Fast.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"assets":[],"ddd":0,"fr":60,"h":500,"ip":0,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Oval 1","hd":false,"sr":1,"ks":{"a":{"a":0,"k":[25,25]},"o":{"a":0,"k":100},"p":{"a":1,"k":[{"t":0,"s":[331.824,250],"i":{"x":0.75,"y":0.75},"o":{"x":0.25,"y":0.25}},{"t":48,"s":[331.824,250.5],"i":{"x":0.88,"y":0.77},"o":{"x":0.5,"y":0},"ti":[0,0],"to":[0,0]},{"t":96,"s":[331.824,250],"i":{"x":0.5,"y":1},"o":{"x":0.12,"y":0.23},"ti":[0,0],"to":[0,0]},{"t":120,"s":[331.824,165],"i":{"x":0.75,"y":0.75},"o":{"x":0.25,"y":0.25},"ti":[0,0],"to":[0,0]},{"t":144,"s":[332.324,250],"i":{"x":0,"y":0},"o":{"x":1,"y":1}}]},"r":{"a":0,"k":0},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}},"ao":0,"ip":0,"op":145,"st":0,"bm":0,"shapes":[{"ty":"el","hd":false,"nm":"Oval 1","p":{"a":0,"k":[25,25]},"s":{"a":0,"k":[50,50]},"d":1},{"ty":"fl","hd":false,"bm":0,"c":{"a":1,"k":[{"t":0,"s":[0.973,0.8,0.725],"i":{"x":0.88,"y":0.77},"o":{"x":0.5,"y":0}},{"t":96,"s":[0.973,0.8,0.725],"i":{"x":0.5,"y":1},"o":{"x":0.12,"y":0.23}},{"t":120,"s":[0.929,0.447,0.239],"i":{"x":0,"y":0},"o":{"x":1,"y":1}}]},"r":1,"o":{"a":0,"k":100}}]},{"ddd":0,"ind":2,"ty":4,"nm":"Oval 1","hd":false,"sr":1,"ks":{"a":{"a":0,"k":[25,25]},"o":{"a":0,"k":100},"p":{"a":1,"k":[{"t":0,"s":[174.176,250.5],"i":{"x":0.88,"y":0.77},"o":{"x":0.5,"y":0},"ti":[0,0],"to":[0,0]},{"t":24,"s":[175,165],"i":{"x":0.5,"y":1},"o":{"x":0.12,"y":0.23},"ti":[0,0],"to":[0,0]},{"t":48,"s":[174.676,250.5],"i":{"x":0,"y":0},"o":{"x":1,"y":1}}]},"r":{"a":0,"k":0},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}},"ao":0,"ip":0,"op":145,"st":0,"bm":0,"shapes":[{"ty":"el","hd":false,"nm":"Oval 1","p":{"a":0,"k":[25,25]},"s":{"a":0,"k":[50,50]},"d":1},{"ty":"fl","hd":false,"bm":0,"c":{"a":1,"k":[{"t":0,"s":[0.929,0.447,0.239],"i":{"x":0.75,"y":0.75},"o":{"x":0.25,"y":0.25}},{"t":48,"s":[0.973,0.8,0.725],"i":{"x":0,"y":0},"o":{"x":1,"y":1}}]},"r":1,"o":{"a":0,"k":100}}]},{"ddd":0,"ind":3,"ty":4,"nm":"Oval 1","hd":false,"sr":1,"ks":{"a":{"a":0,"k":[25,25]},"o":{"a":0,"k":100},"p":{"a":1,"k":[{"t":0,"s":[251.235,250],"i":{"x":0.75,"y":0.75},"o":{"x":0.25,"y":0.25},"ti":[0,0],"to":[0,0]},{"t":48,"s":[251.235,250.5],"i":{"x":0.75,"y":0.75},"o":{"x":0.25,"y":0.25},"ti":[0,0],"to":[0,0]},{"t":72,"s":[251.235,165],"i":{"x":0.75,"y":0.75},"o":{"x":0.25,"y":0.25},"ti":[0,0],"to":[0,0]},{"t":96,"s":[251.235,250],"i":{"x":0,"y":0},"o":{"x":1,"y":1}}]},"r":{"a":0,"k":0},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}},"ao":0,"ip":0,"op":145,"st":0,"bm":0,"shapes":[{"ty":"el","hd":false,"nm":"Oval 1","p":{"a":0,"k":[25,25]},"s":{"a":0,"k":[50,50]},"d":1},{"ty":"fl","hd":false,"bm":0,"c":{"a":1,"k":[{"t":0,"s":[0.973,0.8,0.725],"i":{"x":0.88,"y":0.77},"o":{"x":0.5,"y":0}},{"t":72,"s":[0.929,0.447,0.239],"i":{"x":0.75,"y":0.75},"o":{"x":0.25,"y":0.25}},{"t":96,"s":[0.973,0.8,0.725],"i":{"x":0,"y":0},"o":{"x":1,"y":1}}]},"r":1,"o":{"a":0,"k":100}}]}],"meta":{"g":"@phase-software/lottie-exporter 0.7.0"},"nm":"","op":144,"v":"5.6.0","w":500}
33 changes: 33 additions & 0 deletions src/components/common/loading/LoadingBall.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import styled from '@emotion/styled';
import React from 'react';
import LottieContainer from '../lottie/LottieContainer';

const LoadingBall = () => {
return (
<Overlay>
<Wrapper>
<LottieContainer path="/Ball_Fast.json" isPlay={true} />
</Wrapper>
</Overlay>
);
};

export default LoadingBall;

const Overlay = styled.div`
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: transparent;
display: flex;
justify-content: center;
align-items: center;
z-index: 100000;
`;

const Wrapper = styled.div`
width: 160px;
height: 160px;
`;
112 changes: 32 additions & 80 deletions src/components/home/post/Image/ImagePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import React, { useCallback, useEffect, useState } from 'react';
import styled from '@emotion/styled';
import { motion, useAnimation } from 'framer-motion';
import { colors } from '@styles/theme';

interface ImagePickerProps {
images?: string[] | [];
}

const ImagePicker: React.FC<ImagePickerProps> = (props): JSX.Element => {
const [pickers, setPickers] = useState<JSX.Element[]>([]);
const [pickIndex, setPickIndex] = useState<number>(0);
const [startX, setStartX] = useState<number | null>(null);
const [endX, setEndX] = useState<number | null>(null);

const minSwipeDistance = 50;
const controls = useAnimation();
const [dragStart, setDragStart] = useState<number | null>(null);

const onPickIndex = useCallback(
(idx: number): void => {
Expand All @@ -24,97 +22,53 @@ const ImagePicker: React.FC<ImagePickerProps> = (props): JSX.Element => {
[pickIndex]
);

const handleStart = (clientX: number) => {
setEndX(null);
setStartX(clientX);
};

const handleMove = (clientX: number) => {
setEndX(clientX);
const handleDragStart = (event: any) => {
setDragStart(event.clientX || event.touches[0].clientX);
};

const handleEnd = () => {
if (!startX || !endX) return;
const distance = startX - endX;
const isLeftSwipe = distance > minSwipeDistance;
const isRightSwipe = distance < -minSwipeDistance;
const handleDragEnd = (event: any) => {
const clientX = event.clientX || (event.changedTouches && event.changedTouches[0].clientX);
if (dragStart === null || clientX === undefined) return;
const distance = dragStart - clientX;
const minSwipeDistance = 50;

if (isLeftSwipe && pickIndex < (props.images ?? []).length - 1) {
if (distance > minSwipeDistance && pickIndex < (props.images ?? []).length - 1) {
setPickIndex((prev) => prev + 1);
}
if (isRightSwipe && pickIndex > 0) {
} else if (distance < -minSwipeDistance && pickIndex > 0) {
setPickIndex((prev) => prev - 1);
}
};

// Touch events
const onTouchStart = (e: React.TouchEvent<HTMLDivElement>) => {
handleStart(e.touches[0].clientX);
};

const onTouchMove = (e: React.TouchEvent<HTMLDivElement>) => {
handleMove(e.touches[0].clientX);
};

const onTouchEnd = () => {
handleEnd();
};

// Mouse events
const onMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
handleStart(e.clientX);
};

const onMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
if (startX === null) return; // Only move if we've started
handleMove(e.clientX);
};

const onMouseUp = () => {
handleEnd();
setStartX(null); // Reset start position
};

const onMouseLeave = () => {
if (startX !== null) {
handleEnd();
setStartX(null);
}
setDragStart(null);
};

useEffect(() => {
setPickers(
(props.images ?? []).map((_: string, idx: number) => {
return (
<Picker
key={idx}
onClick={() => onPickIndex(idx)}
background={pickIndex === idx ? colors.red600 : 'white'}
border={pickIndex === idx ? colors.red100 : colors.gray300}
/>
);
})
);
}, [onPickIndex, pickIndex, props.images]);
controls.start({ x: -pickIndex * 100 + '%' });
}, [pickIndex, controls]);

return (
<Container
onTouchStart={onTouchStart}
onTouchMove={onTouchMove}
onTouchEnd={onTouchEnd}
onMouseDown={onMouseDown}
onMouseMove={onMouseMove}
onMouseUp={onMouseUp}
onMouseLeave={onMouseLeave}
onMouseDown={handleDragStart}
onMouseUp={handleDragEnd}
onMouseLeave={handleDragEnd}
onTouchStart={handleDragStart}
onTouchEnd={handleDragEnd}
>
<ImageContainer translateX={-pickIndex * 100}>
<ImageContainer animate={controls}>
{props.images?.map((image, index) => (
<ImageWrapper key={index}>
<FillImage src={image} alt={`Image ${index + 1}`} />
</ImageWrapper>
))}
</ImageContainer>
<PickerWrapper>{pickers}</PickerWrapper>
<PickerWrapper>
{(props.images ?? []).map((_, idx: number) => (
<Picker
key={idx}
onClick={() => onPickIndex(idx)}
background={pickIndex === idx ? colors.red600 : 'white'}
border={pickIndex === idx ? colors.red100 : colors.gray300}
/>
))}
</PickerWrapper>
</Container>
);
};
Expand All @@ -129,10 +83,9 @@ const Container = styled.div`
cursor: pointer;
`;

const ImageContainer = styled.div<{ translateX: number }>`
const ImageContainer = styled(motion.div)`
display: flex;
transition: transform 0.25s ease-out;
transform: translateX(${(props) => props.translateX}%);
`;

const ImageWrapper = styled.div`
Expand All @@ -150,7 +103,6 @@ const FillImage = styled.img`
`;

const PickerWrapper = styled.div`
/* height: 100%; */
align-items: center;
justify-content: center;
display: flex;
Expand Down
2 changes: 2 additions & 0 deletions src/routers/auth/oauth/KakaoRedirect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useMutation } from 'react-query';
import axios from 'axios';
import useAuthStore from '@stores/auth';
import Loading from '@components/common/loading/Loading';
import { apiClient } from '@apis/axios';

interface KakaoLoginResponse {
accessToken: string;
Expand All @@ -24,6 +25,7 @@ const KakaoRedirect = () => {

const kakaoLogin = async (code: string) => {
try {
apiClient.defaults.withCredentials = true;
const response = await axios.get(`https://api.stuffinout.site/kakaologin?code=${code}`, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' },
});
Expand Down
2 changes: 1 addition & 1 deletion src/routers/home/detail/Detail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ const Detail = () => {
| undefined;

const handleArrowClick = () => {
navigate(-1);
postDetail?.ownerId === memberId ? navigate('/') : navigate(-1);
};

const handleHomeClick = () => {
Expand Down
9 changes: 8 additions & 1 deletion src/routers/home/introduce/Introduce.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@ const Introduce = () => {
};
return (
<Layout
HeaderLeft={<LeftArrowIcon onClick={handleBack} />}
HeaderLeft={
<LeftArrowIcon
onClick={handleBack}
css={css`
cursor: pointer;
`}
/>
}
HeaderCenter={<Txt variant="t20">팀 maximalist 소개</Txt>}
Footer
>
Expand Down
2 changes: 1 addition & 1 deletion src/routers/home/post/Post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ const Post = () => {
setIsCloseAlert(true);
return false;
}
if (fileList.length < 1) {
if (fileList.length < 1 && pictures.length < 1) {
setAlertContent(
<Col gap={'12'} alignItems="center">
<Txt variant="t20">사진은 중요!</Txt>
Expand Down
65 changes: 55 additions & 10 deletions src/routers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,20 @@ import Signup from '@routers/auth/signup/Signup';
import Login from '@routers/auth/login/Login';
import PwdSearch from '@routers/auth/pwdsearch/PwdSearch';
import NickNameSetting from '@routers/auth/nickname/NickNameSetting';
import MyHome from '@routers/home/MyHome';
import NickNameChange from '@routers/home/homemenu/NickNameChange';
import PwdChange from '@routers/home/homemenu/PwdChange';
import Post from '@routers/home/post/Post';
import useAuthStore from '@stores/auth';
import Detail from '@routers/home/detail/Detail';
import Error from '@routers/error/Error';
import KakaoRedirect from '@routers/auth/oauth/KakaoRedirect';
import Introduce from '@routers/home/introduce/Introduce';
import OthersStuffList from '@routers/home/homemenu/OthersStuffList';
import GoogleRedirect from './auth/oauth/GoogleRedirect';
import { lazy, Suspense } from 'react';
import LoadingBall from '@components/common/loading/LoadingBall';

const Post = lazy(() => import('@routers/home/post/Post'));
const MyHome = lazy(() => import('@routers/home/MyHome'));
const Detail = lazy(() => import('@routers/home/detail/Detail'));

const ProtectedRoute = () => {
const isLoggedin = useAuthStore((store) => store.isLoggedIn);
Expand All @@ -42,14 +45,49 @@ const Router = () => {
const router = createBrowserRouter(
createRoutesFromElements(
<>
<Route path="*" element={<ProtectedRoute />}>
<Route element={<ProtectedRoute />}>
<Route path="pwd" element={<PwdChange />} />
<Route path="post" element={<Post />} />
<Route
path="post"
element={
<Suspense fallback={<LoadingBall />}>
<Post />
</Suspense>
}
/>
<Route path="nickname" element={<NickNameChange />} />
<Route path="others-home" element={<OthersStuffList />} />
<Route path="detail/:postId" element={<Detail />} />
<Route index element={<MyHome />} />
<Route path="other/:ownerId" element={<MyHome />} />
<Route
path="others-home"
element={
<Suspense fallback={<LoadingBall />}>
<OthersStuffList />
</Suspense>
}
/>
<Route
path="detail/:postId"
element={
<Suspense fallback={<LoadingBall />}>
<Detail />
</Suspense>
}
/>
<Route
index
element={
<Suspense fallback={<LoadingBall />}>
<MyHome />
</Suspense>
}
/>
<Route
path="other/:ownerId"
element={
<Suspense fallback={<LoadingBall />}>
<MyHome />
</Suspense>
}
/>
</Route>
<Route path="signup" element={<Signup />} />
<Route path="setting" element={<NickNameSetting />} />
Expand All @@ -58,7 +96,14 @@ const Router = () => {
<Route path="error" element={<Error />} />
<Route path="kakaologin/callback" element={<KakaoRedirect />} />
<Route path="/oauth-callback" element={<GoogleRedirect />} />
<Route path="introduce" element={<Introduce />} />
<Route
path="introduce"
element={
<Suspense fallback={<LoadingBall />}>
<Introduce />
</Suspense>
}
/>
</>
)
);
Expand Down
Loading

0 comments on commit 85022b0

Please sign in to comment.