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

Add: room diff calculation #770

Merged
merged 6 commits into from
May 14, 2024
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
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;
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) => {
predict-woo marked this conversation as resolved.
Show resolved Hide resolved
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;
}
`;
predict-woo marked this conversation as resolved.
Show resolved Hide resolved

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);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10초마다 backend에 API request 를 날리는 군요 ㅜㅜㅜ
우리 서버 힘들겠군.. ㅜ

useSWR 이나 useQuery 쓰면 인터벌 하게 API 값 갱신하는 것 수동으로 안해줘도 될듯요?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이걸로 변경해보겠습니다!

return () => clearInterval(interval);
}, []);

Expand Down
120 changes: 62 additions & 58 deletions packages/web/src/pages/Myroom/R1Myroom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Link } from "react-router-dom";
import AdaptiveDiv from "@/components/AdaptiveDiv";
import Empty from "@/components/Empty";
import Pagination, { PAGE_MAX_ITEMS } from "@/components/Pagination";
import Room from "@/components/Room";
import AnimatedRoom from "@/components/Room/AnimatedRoom";
import Title from "@/components/Title";

/**
Expand All @@ -23,63 +23,67 @@ const R1Myroom = ({
ongoing = [],
done = [],
donePageInfo,
}: R1MyroomProps) => (
<AdaptiveDiv type="center">
<Title icon="current" isHeader>
참여 중인 방
</Title>
{ongoing.length === 0 ? (
<Empty type="mobile">참여 중인 방이 없습니다</Empty>
) : (
ongoing.map((item) => (
<Link
key={item._id}
to={`/myroom/${item._id}`}
style={{ textDecoration: "none" }}
>
<Room
data={item}
selected={roomId === item._id}
theme="white"
marginBottom="15px"
}: R1MyroomProps) => {
return (
<AdaptiveDiv type="center">
<Title icon="current" isHeader>
참여 중인 방
</Title>
{ongoing?.length === 0 ? (
<Empty type="mobile">참여 중인 방이 없습니다</Empty>
) : (
ongoing.map((item) => (
<Link
key={item._id}
to={`/myroom/${item._id}`}
style={{ textDecoration: "none" }}
>
<AnimatedRoom
data={item}
selected={roomId === item._id}
theme="white"
marginBottom="15px"
type={item.type}
/>
</Link>
))
)}
<Title icon="past" isHeader>
과거 참여 방
</Title>
{done?.length === 0 ? (
<Empty type="mobile">과거 참여했던 방이 없습니다</Empty>
) : (
<>
{done
?.slice(
PAGE_MAX_ITEMS * (donePageInfo.currentPage - 1),
PAGE_MAX_ITEMS * donePageInfo.currentPage
)
.map((item) => (
<Link
key={item._id}
to={`/myroom/${item._id}`}
style={{ textDecoration: "none" }}
>
<AnimatedRoom
data={item}
selected={roomId === item._id}
theme="white"
marginTop="15px"
type={item.type}
/>
</Link>
))}
<Pagination
totalPages={donePageInfo.totalPages}
currentPage={donePageInfo.currentPage}
isMobile
/>
</Link>
))
)}
<Title icon="past" isHeader>
과거 참여 방
</Title>
{done.length === 0 ? (
<Empty type="mobile">과거 참여했던 방이 없습니다</Empty>
) : (
<>
{done
.slice(
PAGE_MAX_ITEMS * (donePageInfo.currentPage - 1),
PAGE_MAX_ITEMS * donePageInfo.currentPage
)
.map((item) => (
<Link
key={item._id}
to={`/myroom/${item._id}`}
style={{ textDecoration: "none" }}
>
<Room
data={item}
selected={roomId === item._id}
theme="white"
marginTop="15px"
/>
</Link>
))}
<Pagination
totalPages={donePageInfo.totalPages}
currentPage={donePageInfo.currentPage}
isMobile
/>
</>
)}
</AdaptiveDiv>
);
</>
)}
</AdaptiveDiv>
);
};

export default R1Myroom;
Loading
Loading