Skip to content

Commit

Permalink
Merge pull request #788 from sparcs-kaist/dev
Browse files Browse the repository at this point in the history
Main branch update from Dev branch
  • Loading branch information
kmc7468 authored May 21, 2024
2 parents d879be5 + 0e4181a commit 917be6b
Show file tree
Hide file tree
Showing 17 changed files with 358 additions and 97 deletions.
10 changes: 8 additions & 2 deletions packages/web/src/components/Chat/Header/SideMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ const SideMenu = ({ roomInfo, isOpen, setIsOpen }: SideMenuProps) => {
const onClickCallTaxi = useCallback(() => setIsOpenCallTaxi(true), []);
const onClickReport = useCallback(() => setIsOpenReport(true), []);

const isAlone = roomInfo.part.length === 1;

const styleBackground = {
position: "absolute" as any,
top: 0,
Expand Down Expand Up @@ -192,8 +194,12 @@ const SideMenu = ({ roomInfo, isOpen, setIsOpen }: SideMenuProps) => {
<SideMenuButton type="share" onClick={onClikcShare} />
<DottedLine />
<SideMenuButton type="taxi" onClick={onClickCallTaxi} />
<DottedLine />
<SideMenuButton type="report" onClick={onClickReport} />
{!isAlone && (
<>
<DottedLine />
<SideMenuButton type="report" onClick={onClickReport} />
</>
)}
</div>
<DottedLine />
<div css={styleNameSection} onClick={onClickCancel}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const MessageSet = ({ chats, layoutType, roomInfo }: MessageSetProps) => {
const authorName = "authorName" in chats?.[0] ? chats?.[0].authorName : "";

const isBot = authorId === "bot";
const isAlone = roomInfo.part.length === 1;

const style = {
position: "relative" as any,
Expand Down Expand Up @@ -148,8 +149,11 @@ const MessageSet = ({ chats, layoutType, roomInfo }: MessageSetProps) => {
<div css={styleProfileSection}>
{authorId !== userOid && (
<div
css={{ ...styleProfile, cursor: !isBot ? "pointer" : undefined }}
onClick={() => !isBot && onClickProfileImage()}
css={{
...styleProfile,
cursor: !isBot && !isAlone ? "pointer" : undefined,
}}
onClick={() => !isBot && !isAlone && onClickProfileImage()}
>
{isBot ? (
<TaxiIcon css={{ width: "100%", height: "100%" }} />
Expand Down
14 changes: 10 additions & 4 deletions packages/web/src/components/ModalPopup/Body/BodyRoomSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ const BodyRoomSelection = ({ roomInfo }: BodyRoomSelectionProps) => {
const isDepart = useIsTimeOver(dayServerToClient(roomInfo.time)); // 방 출발 여부

const requestJoin = useCallback(async () => {
if (isAlreadyPart) {
// 이미 참여 중인 방에서 버튼을 누르면 API 호출 관련 로직을 건너뛰고 해당 방으로 이동합니다.
history.push(`/myroom/${roomInfo._id}`);
return;
}
// 여기부터는 이미 참여 중인 방이 아닌 경우의 로직입니다.
if (onCall.current) return;
onCall.current = true;
await axios({
Expand Down Expand Up @@ -204,18 +210,18 @@ const BodyRoomSelection = ({ roomInfo }: BodyRoomSelectionProps) => {
{isLogin || isRoomFull || isDepart ? (
<Button
type="purple"
disabled={isRoomFull || isDepart || isAlreadyPart || isMaxPart}
disabled={(isRoomFull || isDepart || isMaxPart) && !isAlreadyPart}
css={{
padding: "10px 0 9px",
borderRadius: "8px",
...theme.font14_bold,
}}
onClick={requestJoin}
>
{isAlreadyPart
? "이미 참여 중입니다"
: isDepart
{isDepart && !isAlreadyPart
? "출발 시각이 현재 이전인 방은 참여할 수 없습니다"
: isAlreadyPart
? "이미 참여 중입니다 : 바로가기"
: isRoomFull
? "남은 인원이 0명인 방은 참여할 수 없습니다"
: isMaxPart
Expand Down
65 changes: 65 additions & 0 deletions packages/web/src/components/Room/AnimatedRoom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { keyframes } from "@emotion/react";

import Room from ".";

type AnimatedRoomProps = {
data: any;
selected?: boolean;
onClick?: () => void;
marginTop?: string;
marginBottom?: string;
theme?: string;
type?: "addition" | "deletion";
};

const growHeight = keyframes`
from {
height: 0px;
}
to {
height: 125px;
}
`;

const shrinkHeight = keyframes`
from {
height: 125px;
}
to {
height: 0px;
}
`;

const AnimatedRoom = ({
data,
selected = false,
onClick = () => {},
marginTop = "0px",
marginBottom = "0px",
theme,
type,
}: AnimatedRoomProps) => {
const props = {
data,
selected,
onClick,
marginTop,
marginBottom,
theme,
type,
};

return !data.animating ? (
<Room {...props} />
) : (
<div
css={{
animation: `${
type === "addition" ? growHeight : shrinkHeight
} 0.5s forwards`,
}}
></div>
);
};

export default AnimatedRoom;
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ class ChannelService {
updateUser(options) {
window.ChannelIO("updateUser", options);
}
openChat(message) {
window.ChannelIO("openChat", undefined, message);
}
shutdown() {
window.ChannelIO("shutdown");
}
Expand Down
79 changes: 79 additions & 0 deletions packages/web/src/hooks/useRoomListAnimationState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { useEffect, useState } from "react";

const useRoomListAnimationState = (rooms: Nullable<Array<any>>) => {
const [state, setState] = useState<
"default" | "additionAnimate" | "addition" | "deletionAnimate" | "deletion"
>("default");

const [localRooms, setLocalRooms] = useState(rooms);

const animateDeletion = () => {
const deletionRooms = localRooms?.map((localRoom) => {
if (!rooms?.find((room) => room._id === localRoom._id)) {
return { ...localRoom, animating: true, type: "deletion" };
}
return localRoom;
});
setLocalRooms(deletionRooms);
const timer = setTimeout(() => {
setState("deletion");
}, 500);

return () => clearTimeout(timer);
};

const deletion = () => {
setLocalRooms(localRooms?.filter((room) => room.type !== "deletion"));
setState("additionAnimate");
};

const animateAddition = () => {
let additionRooms = rooms?.map((room, index) => {
if (!localRooms?.find((localRoom) => localRoom._id === room._id)) {
return { ...room, animating: true, type: "addition" };
}
return room;
});
setLocalRooms(additionRooms);
const timer = setTimeout(() => {
setState("addition");
}, 500);
return () => clearTimeout(timer);
};

const addition = () => {
setLocalRooms(rooms);
setState("default");
};

useEffect(() => {
if (rooms && localRooms?.length && rooms.length !== localRooms.length) {
setState("deletionAnimate");
} else {
setLocalRooms(rooms);
}
}, [rooms]);

useEffect(() => {
switch (state) {
case "deletionAnimate":
animateDeletion();
break;
case "deletion":
deletion();
break;
case "additionAnimate":
animateAddition();
break;
case "addition":
addition();
break;
default:
break;
}
}, [state]);

return { localRooms, state };
};

export default useRoomListAnimationState;
47 changes: 47 additions & 0 deletions packages/web/src/pages/Home/NewRoom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { keyframes } from "@emotion/react";
import { useEffect, useState } from "react";

import Room from "@/components/Room";

const DiffRoom = (props: any) => {
const [animating, setAnimating] = useState(true);

useEffect(() => {
const timer = setTimeout(() => {
setAnimating(false);
}, 500);
return () => clearTimeout(timer);
}, []);

const growHeight = keyframes`
from {
height: 0px;
}
to {
height: 125px;
}
`;

const shrinkHeight = keyframes`
from {
height: 125px;
}
to {
height: 0px;
}
`;

const animation = props.type === "addition" ? growHeight : shrinkHeight;

return animating ? (
<div
css={{
animation: `${animation} 0.5s forwards`,
}}
></div>
) : props.type === "addition" ? (
<Room data={props.room} marginBottom={props.marginBottom} />
) : null;
};

export default DiffRoom;
16 changes: 11 additions & 5 deletions packages/web/src/pages/Home/RoomList.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Link } from "react-router-dom";

import usePageFromSearchParams from "@/hooks/usePageFromSearchParams";
import useRoomListAnimationState from "@/hooks/useRoomListAnimationState";

import Empty from "@/components/Empty";
import Pagination, { PAGE_MAX_ITEMS } from "@/components/Pagination";
import Room from "@/components/Room";
import AnimatedRoom from "@/components/Room/AnimatedRoom";

type RoomListProps = {
rooms: Nullable<Array<any>>;
Expand All @@ -13,12 +14,13 @@ type RoomListProps = {
const RoomList = (props: RoomListProps) => {
const totalPages = Math.ceil((props.rooms ?? []).length / PAGE_MAX_ITEMS);
const currentPage = usePageFromSearchParams(totalPages);
const { localRooms } = useRoomListAnimationState(props.rooms);

return (
<>
{props.rooms?.length ? (
{localRooms?.length ? (
<>
{props.rooms
{localRooms
?.slice(
PAGE_MAX_ITEMS * (currentPage - 1),
PAGE_MAX_ITEMS * currentPage
Expand All @@ -30,10 +32,14 @@ const RoomList = (props: RoomListProps) => {
replace
style={{ textDecoration: "none" }}
>
<Room data={room} marginBottom="15px" />
<AnimatedRoom
data={room}
marginBottom="15px"
type={room.type}
/>
</Link>
))}
{props.rooms.length > PAGE_MAX_ITEMS && (
{localRooms.length > PAGE_MAX_ITEMS && (
<Pagination
totalPages={totalPages}
currentPage={currentPage}
Expand Down
4 changes: 2 additions & 2 deletions packages/web/src/pages/Home/RoomSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ const RoomSection = ({ roomId }: RoomSectionProps) => {

const [roomInfo, setRoomInfo] = useState<Nullable<any>>(null);

// 5분 간격으로 allRoms(요일 별 출발하는 방)을 갱신합니다.
// 10초 간격으로 allRoms(요일 별 출발하는 방)을 갱신합니다.
useEffect(() => {
const interval = setInterval(fetchAllRooms, 1000 * 60 * 5);
const interval = setInterval(fetchAllRooms, 1000 * 10);
return () => clearInterval(interval);
}, []);

Expand Down
3 changes: 3 additions & 0 deletions packages/web/src/pages/Mypage/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import ExitToAppRoundedIcon from "@mui/icons-material/ExitToAppRounded";
import HelpOutlineRoundedIcon from "@mui/icons-material/HelpOutlineRounded";
import KeyboardArrowLeftRoundedIcon from "@mui/icons-material/KeyboardArrowLeftRounded";
import LanguageRoundedIcon from "@mui/icons-material/LanguageRounded";
import PersonRemoveRoundedIcon from "@mui/icons-material/PersonRemoveRounded";
import PortraitRoundedIcon from "@mui/icons-material/PortraitRounded";
import StarRoundedIcon from "@mui/icons-material/StarRounded";

Expand Down Expand Up @@ -46,6 +47,8 @@ const getIcon = (icon: string) => {
return <AlarmOffRoundedIcon style={styleIcon} />;
case "logout":
return <ExitToAppRoundedIcon style={styleIcon} />;
case "cancel_account":
return <PersonRemoveRoundedIcon style={styleIcon} />;
case "beta":
return <StarRoundedIcon style={styleIcon} />;
}
Expand Down
12 changes: 11 additions & 1 deletion packages/web/src/pages/Mypage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import WhiteContainerSuggestLogin from "@/components/WhiteContainer/WhiteContain

import Menu from "./Menu";

import { eventMode, isDev } from "@/tools/loadenv";
import { deviceType, eventMode, isDev } from "@/tools/loadenv";
import theme from "@/tools/theme";
import { isNotificationOn } from "@/tools/trans";

Expand Down Expand Up @@ -74,6 +74,11 @@ const Mypage = () => {
);
const onClickEventPolicy = useCallback(() => setIsOpenEventPolicy(true), []);
const onClickMembers = useCallback(() => setOpenIsMembers(true), []);
const onClickCancelAccount = useCallback(() => {
channelService.openChat(
"SPARCS Taxi 서비스의 계정 탈퇴를 신청하고 싶습니다.\n신청 사유는 다음과 같습니다:\n"
);
}, []);

const styleProfImg = {
width: "50px",
Expand Down Expand Up @@ -209,6 +214,11 @@ const Mypage = () => {
<Menu icon="logout">{t("logout")}</Menu>
</LinkLogout>
)}
{userId && deviceType.startsWith("app/") && (
<Menu icon="cancel_account" onClick={onClickCancelAccount}>
{t("cancel_account")}
</Menu>
)}
</div>
</WhiteContainer>
<Footer type="only-logo" />
Expand Down
Loading

0 comments on commit 917be6b

Please sign in to comment.