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

프론트에서 darakbang URL 구현 #406

Merged
merged 16 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
12 changes: 10 additions & 2 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import { Global, ThemeProvider } from '@emotion/react';
import { useEffect, useMemo } from 'react';

import { QueryClientProvider } from '@tanstack/react-query';
import { RouterProvider } from 'react-router-dom';
import createQueryClient from './queryClient';
import fonts from '@_common/font.style';
import { removeInviteCode } from '@_common/inviteCodeManager';
import reset from './common/reset.style';
import { useMemo } from 'react';
import { theme } from '@_common/theme/theme.style';
import router from '@_routes/router';
import { theme } from '@_common/theme/theme.style';

export default function App() {
const queryClient = useMemo(createQueryClient, []);

useEffect(() => {
window.addEventListener('beforeunload', removeInviteCode);

return window.removeEventListener('beforeunload', removeInviteCode);
});

return (
<ThemeProvider theme={theme}>
<Global styles={[reset, fonts]} />
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/apis/posts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,14 @@ export const postDarakbang = async ({
name: string;
nickname: string;
}) => {
await ApiClient.postWithAuth('darakbang', {
const response = await ApiClient.postWithAuth('darakbang', {
name,
nickname,
});

const json = await response.json();

return json?.data;
};

export const postDarakbangEntrance = async ({
Expand Down
29 changes: 29 additions & 0 deletions frontend/src/common/getRoutes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { getLastDarakbangId } from './lastDarakbangManager';

const getDarakbangIdRoute = (darakbangId: number) =>
'/darakbang/' + darakbangId;

const getNowDarakbangRoute = () =>
getDarakbangIdRoute(getLastDarakbangId() || 0);

const GET_ROUTES = {
nowDarakbang: {
main: () => getNowDarakbangRoute(),
addMoim: () => getNowDarakbangRoute() + '/add-moim',
moimDetail: (moimId: number) => getNowDarakbangRoute() + '/moim/' + moimId,
moimParticipateComplete: () =>
getNowDarakbangRoute() + '/moim/participation-complete',
modify: (moimId: number) => getNowDarakbangRoute() + '/modify/' + moimId,
chat: () => getNowDarakbangRoute() + '/chat',
chattingRoom: (moimId: number) =>
getNowDarakbangRoute() + '/chatting-room/' + moimId,
please: () => getNowDarakbangRoute() + '/please',
addPlease: () => getNowDarakbangRoute() + '/please/creation',
myPage: () => getNowDarakbangRoute() + '/my-page',
notification: () => getNowDarakbangRoute() + '/notification',
darakbangManagement: () => getNowDarakbangRoute() + '/darakbang-management',
darakbangMembers: () => getNowDarakbangRoute() + '/darakbang-members',
darakbangInvitation: () => getNowDarakbangRoute() + '/darakbang-invitation',
},
};
export default GET_ROUTES;
15 changes: 15 additions & 0 deletions frontend/src/common/inviteCodeManager.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const INVITE_CODE_KEY = 'invite-code';

export const setInviteCode = (inviteCode: string): void => {
localStorage.setItem(INVITE_CODE_KEY, inviteCode);
};

export const getInviteCode = () => {
const inviteCode = localStorage.getItem(INVITE_CODE_KEY);
if (!inviteCode) return null;
return inviteCode;
};

export const removeInviteCode = () => {
localStorage.removeItem(INVITE_CODE_KEY);
};
5 changes: 3 additions & 2 deletions frontend/src/components/MoimCardList/MoimCardList.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as S from './MoimCardList.style';

import GET_ROUTES from '@_common/getRoutes';
import MoimCard from '../MoimCard/MoimCard';
import { MoimInfo } from '@_types/index';
import { useNavigate } from 'react-router-dom';
import MoimCard from '../MoimCard/MoimCard';

interface MoimCardListProps {
moimInfos: MoimInfo[];
Expand All @@ -14,7 +15,7 @@ export default function MoimCardList(props: MoimCardListProps) {
const navigate = useNavigate();

const handleMoimCard = (moimId: number) => {
navigate(`/moim/${moimId}`);
navigate(GET_ROUTES.nowDarakbang.moimDetail(moimId));
};

return (
Expand Down
16 changes: 9 additions & 7 deletions frontend/src/components/NavigationBar/NavigationBar.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import * as S from './NavigationBar.style';
import { useState } from 'react';

import { useLocation, useNavigate } from 'react-router-dom';

import GET_ROUTES from '@_common/getRoutes';
import NavigationBarItem from '@_components/NavigationBarItem/NavigationBarItem';
import { useState } from 'react';
import { useTheme } from '@emotion/react';
import { useLocation, useNavigate } from 'react-router-dom';
import ROUTES from '@_constants/routes';

export type Tab = '홈' | '채팅' | '해주세요' | '마이페이지';

const tabRoutes: Record<Tab, string> = {
홈: ROUTES.main,
채팅: ROUTES.chat,
해주세요: ROUTES.please,
마이페이지: ROUTES.myPage,
홈: GET_ROUTES.nowDarakbang.main(),
채팅: GET_ROUTES.nowDarakbang.chat(),
해주세요: GET_ROUTES.nowDarakbang.addPlease(),
마이페이지: GET_ROUTES.nowDarakbang.myPage(),
};

export default function NavigationBar() {
Expand Down
41 changes: 32 additions & 9 deletions frontend/src/constants/routes.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,50 @@
const ROUTES = {
main: '/',
const addDarakbangPrefix = (route: string) => {
return '/darakbang/:darakbangId' + route;
};

const beforeUsingDarakbangPrefixRoutes = {
darakbangMain: '/',
addMoim: '/add-moim',
detail: '/moim/:moimId',
moimDetail: '/moim/:moimId',
participationComplete: '/moim/participation-complete',
home: '/home',
kakaoOAuth: '/kakao-o-auth',
modify: '/modify/:moimId',
chat: '/chat',
chattingRoom: '/chatting-room/:moimId',
please: '/please',
addPlease: '/please/creation',
myPage: '/my-page',
notification: '/notification',
darakbangManagement: '/darakbang-management',
darakbangMembers: '/darakbang-members',
darakbangInvitation: '/darakbang-invitation',
};

const usingDarakbangPrefixRoutes = Object.entries(
beforeUsingDarakbangPrefixRoutes,
).reduce(
(object, [key, routes]) => {
object[key as keyof typeof beforeUsingDarakbangPrefixRoutes] =
addDarakbangPrefix(routes);
return object;
},
{} as Record<keyof typeof beforeUsingDarakbangPrefixRoutes, string>,
);

const ROUTES = {
main: '/',
home: '/home',
kakaoOAuth: '/kakao-o-auth',
darakbangInvitationRoute: '/darakbang-invitation-route',

darakbangSelectOption: '/darakbang-select-option',
darakbangSelect: '/darakbang-select',
darakbangCreation: '/darakbang-creation',
darakbangEntrance: '/darakbang-entrance',
darakbangNickname: '/darakbang-nickname',
darakbangLanding: '/darakbang-landing',
darakbangManagement: '/darakbang-management',
darakbangMembers: '/darakbang-members',
darakbangInvitation: '/darakbang-invitation',
darakbangInvitationRoute: '/darakbang-invitation-route',

// /darakbang/:darakbangId/[루트] 형식
...usingDarakbangPrefixRoutes,
};

export default ROUTES;
6 changes: 3 additions & 3 deletions frontend/src/hooks/mutaions/useCreateDarakbang.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import QUERY_KEYS from '@_constants/queryKeys';
import { postDarakbang } from '@_apis/posts';

export default function useCreateDarakbang(onSuccess?: () => void) {
export default function useCreateDarakbang(onSuccess?: (id: number) => void) {
const queryClient = useQueryClient();

return useMutation({
mutationFn: postDarakbang,
onSuccess: () => {
onSuccess: (id: number) => {
queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.myDarakbangs] });

if (onSuccess) onSuccess();
if (onSuccess) onSuccess(id);
},
});
}
7 changes: 6 additions & 1 deletion frontend/src/pages/ChatPage/ChatPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import ChattingPreview from '@_components/ChattingPreview/ChattingPreview';
import ChattingPreviewLayout from '@_layouts/ChattingPreviewLayout/ChattingPreviewLayout';
import GET_ROUTES from '@_common/getRoutes';
import MissingFallback from '@_components/MissingFallback/MissingFallback';
import NavigationBar from '@_components/NavigationBar/NavigationBar';
import NavigationBarWrapper from '@_layouts/components/NavigationBarWrapper/NavigationBarWrapper';
Expand All @@ -24,7 +25,11 @@ export default function ChatPage() {
chatPreviews?.map((chatPreview) => (
<ChattingPreview
chatPreview={chatPreview}
onClick={() => navigate('/chatting-room/' + chatPreview.moimId)}
onClick={() =>
navigate(
GET_ROUTES.nowDarakbang.chattingRoom(chatPreview.moimId),
)
}
key={chatPreview.moimId}
/>
))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,25 @@ import { ChangeEvent, useState } from 'react';
import Button from '@_components/Button/Button';
import DarakbangCreationModalContent from './DarakbangCreationModalContent/DarakbangCreationModalContent';
import ErrorControlledInput from '@_components/ErrorControlledInput/ErrorControlledInput';
import GET_ROUTES from '@_common/getRoutes';
import HighlightSpan from '@_components/HighlightSpan/HighlightSpan';
import Modal from '@_components/Modal/Modal';
import POLICES from '@_constants/poclies';
import ROUTES from '@_constants/routes';
import SelectLayout from '@_layouts/SelectLayout/SelectLayout';
import SolidArrow from '@_components/Icons/SolidArrow';
import { setLastDarakbangId } from '@_common/lastDarakbangManager';
import useCreateDarakbang from '@_hooks/mutaions/useCreateDarakbang';
import { useNavigate } from 'react-router-dom';
import { useTheme } from '@emotion/react';

export default function DarakbangCreationPage() {
const theme = useTheme();
const navigate = useNavigate();
const { mutate: createDarakbang } = useCreateDarakbang(() =>
navigate(ROUTES.main),
const { mutate: createDarakbang } = useCreateDarakbang(
(darakbangId: number) => {
setLastDarakbangId(darakbangId);
navigate(GET_ROUTES.nowDarakbang.main());
},
);

const [darakbangName, setDarakbangName] = useState('');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ChangeEvent, useState } from 'react';
import Button from '@_components/Button/Button';
import ErrorControlledInput from '@_components/ErrorControlledInput/ErrorControlledInput';
import POLICES from '@_constants/poclies';
import ROUTES from '@_constants/routes';
import SelectLayout from '@_layouts/SelectLayout/SelectLayout';
import SolidArrow from '@_components/Icons/SolidArrow';
import { useNavigate } from 'react-router-dom';
Expand All @@ -11,7 +12,7 @@ import { useTheme } from '@emotion/react';
export default function DarakbangEntrancePage() {
const theme = useTheme();
const navigate = useNavigate();
const [entranceCode, setEntranceCode] = useState('');
const [inviteCode, setInviteCode] = useState('');
return (
<SelectLayout>
<SelectLayout.Header>
Expand All @@ -33,7 +34,7 @@ export default function DarakbangEntrancePage() {
placeholder="참여코드를 입력하세요"
maxLength={POLICES.entranceCodeLength}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
setEntranceCode(e.target.value.toUpperCase());
setInviteCode(e.target.value.toUpperCase());
}}
style={{ textTransform: 'uppercase' }}
/>
Expand All @@ -42,7 +43,10 @@ export default function DarakbangEntrancePage() {
<Button
shape="bar"
primary
disabled={entranceCode.length !== POLICES.entranceCodeLength}
disabled={inviteCode.length !== POLICES.entranceCodeLength}
onClick={() => {
navigate(`${ROUTES.darakbangInvitationRoute}?code=${inviteCode}`);
}}
>
다락방 참여하기
</Button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import GET_ROUTES from '@_common/getRoutes';
import MenuItem from '@_components/MenuItem/MenuItem';
import ROUTES from '@_constants/routes';
import SolidArrow from '@_components/Icons/SolidArrow';
import TriSectionHeader from '@_layouts/components/TriSectionHeader/TriSectionHeader';
import { useNavigate } from 'react-router-dom';
Expand All @@ -16,11 +16,11 @@ export default function DarakbangManagementPage() {
</TriSectionHeader>
<MenuItem
description="멤버 목록"
onClick={() => navigate(ROUTES.darakbangMembers)}
onClick={() => navigate(GET_ROUTES.nowDarakbang.darakbangMembers())}
/>
<MenuItem
description="멤버 초대"
onClick={() => navigate(ROUTES.darakbangInvitation)}
onClick={() => navigate(GET_ROUTES.nowDarakbang.darakbangInvitation())}
isLastItem
/>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import { ChangeEvent, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { getInviteCode, removeInviteCode } from '@_common/inviteCodeManager';

import Button from '@_components/Button/Button';
import DarakbangNicknameModalContent from './DarakbangNicknameModalContent/DarakbangNicknameModalContent';
import ErrorControlledInput from '@_components/ErrorControlledInput/ErrorControlledInput';
import GET_ROUTES from '@_common/getRoutes';
import HighlightSpan from '@_components/HighlightSpan/HighlightSpan';
import Modal from '@_components/Modal/Modal';
import POLICES from '@_constants/poclies';
import ROUTES from '@_constants/routes';
import SolidArrow from '@_components/Icons/SolidArrow';
import StickyTriSectionHeader from '@_layouts/components/StickyTriSectionHeader/StickyTriSectionHeader';
import StretchContentLayout from '@_layouts/StretchContentLayout/StretchContentLayout';
import useDarakbangNameByCode from '@_hooks/queries/useDarakbangNameByCode';
import useEnterDarakbang from '@_hooks/mutaions/useEnterDarakbang';
import { useNavigate } from 'react-router-dom';

export default function DarakbangNicknamePage() {
const navigate = useNavigate();

const { state } = useLocation();
const { code = 'NULL' } = state;
const code = getInviteCode() || '';

const { darakbangName = '' } = useDarakbangNameByCode(code);
const [nickname, setNickName] = useState('');
Expand All @@ -27,7 +27,8 @@ export default function DarakbangNicknamePage() {

const { mutate: enterDarakbang } = useEnterDarakbang({
onSuccess: () => {
navigate(ROUTES.main);
removeInviteCode();
navigate(GET_ROUTES.nowDarakbang.main());
},
onError: (string: string) => {
setIsModalOpen(false);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as S from './DarakbangSelectPage.style';

import GET_ROUTES from '@_common/getRoutes';
import HighlightSpan from '@_components/HighlightSpan/HighlightSpan';
import MissingFallback from '@_components/MissingFallback/MissingFallback';
import ROUTES from '@_constants/routes';
Expand Down Expand Up @@ -46,7 +47,7 @@ export default function DarakbangSelectPage() {
key={darakbangId}
onClick={() => {
setLastDarakbangId(darakbangId);
navigate(ROUTES.main);
navigate(GET_ROUTES.nowDarakbang.main());
}}
>
{name}
Expand Down
Loading