Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
dca90d6
feat: 임시저장된 편지 삭제 기능 구현 (#84)
tifsy Mar 7, 2025
70051d3
feat: 롤링페이퍼 배포된 api로 연결 수정 (#85)
AAminha Mar 7, 2025
aeab0e6
feat : 알림 2차 기능 구현 (#81)
wldnjs990 Mar 7, 2025
ae17500
fix: 자잘한 이슈 수정 (#86)
nirii00 Mar 7, 2025
62d67cd
feat : 재사용 가능한 페이지네이션 구현 (#92)
wldnjs990 Mar 7, 2025
266d0e5
feat: 편지 공유 요청 수신 조회 기능 구현 (#90)
tifsy Mar 7, 2025
a0f576b
feat : 편지작성, 랜덤편지, 상세페이지 3차 기능구현 (#94)
wldnjs990 Mar 8, 2025
5b4d4ba
feat: 롤링페이퍼 추가 기능 구현 (#95)
AAminha Mar 9, 2025
f0b5b4f
feat: 임시저장 편지 조회 기능 완성 (#97)
tifsy Mar 9, 2025
4aced28
feat : 토스트 UI 구현 + 알림 페이지 코드 작업 90% 완료 + 실시간 알림, 편지 작성 예외처리에 토스트UI 연결…
wldnjs990 Mar 9, 2025
6917b3b
fix: reissue 문제, 내 편지함 data 최신화 문제 해결 (#100)
nirii00 Mar 9, 2025
a8144d5
feat : 알림 페이지 알림 확인 처리 안되던 현상 수정 + 신고페이지 4차 구현 (#101)
wldnjs990 Mar 9, 2025
58df399
feat: 공유 요청 상세 조회 기능 구현 (#106)
tifsy Mar 10, 2025
74ef07b
fix: 임시저장 편지 작성 페이지 이동 경로 문제 해결 (#109)
tifsy Mar 10, 2025
6059368
feat : 신고 등록 API + ReportModal 수정 (#111)
wldnjs990 Mar 10, 2025
2fb1cc6
fix: QA 반영 (#112)
nirii00 Mar 10, 2025
40c2021
feat : 알림 기능 구현 + QA (#114)
wldnjs990 Mar 10, 2025
f55da9f
feat : 임시저장 데이터 바인딩 및 임시저장 덮어씌우기 작업 완료 (#115)
wldnjs990 Mar 10, 2025
5fd9543
refactor: 2차 QA 반영 (#116)
tifsy Mar 10, 2025
b33b576
fix: 롤링페이퍼 QA 반영 (#120)
AAminha Mar 10, 2025
65f982b
feat : 알림 QA 수정 (#124)
wldnjs990 Mar 10, 2025
a441bd7
deploy : 배포 (#126)
wldnjs990 Mar 10, 2025
a1f9e59
fix: 3차 QA 반영 (#131)
nirii00 Mar 11, 2025
e2d90da
feat: 다크모드 구현 (#132)
nirii00 Mar 11, 2025
f748ef3
fix: 3차 QA 반영 (#133)
tifsy Mar 11, 2025
3b83467
feat : QA반영 (#134)
wldnjs990 Mar 11, 2025
19c4b17
Merge branch 'main' of https://github.com/prgrms-web-devcourse-final-…
wldnjs990 Mar 11, 2025
4464f29
deploy : 수정
wldnjs990 Mar 11, 2025
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: 12 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,22 @@ import RandomLettersPage from './pages/RandomLetters';
import RollingPaperPage from './pages/RollingPaper';
import WritePage from './pages/Write';
import ShareApprovalPage from './pages/Share';
import useThemeStore from './stores/themeStore';

const App = () => {
const theme = useThemeStore((state) => state.theme);
useViewport();

const initializeTheme = () => {
if (theme === 'dark') {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
};

initializeTheme();

return (
<Routes>
<Route element={<MobileLayout />}>
Expand Down
29 changes: 25 additions & 4 deletions src/apis/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ const patchReport = async (reportId: number, patchReportRequest: PatchReportRequ
};

// badwords
const getBadWords = async (setBadWords: React.Dispatch<React.SetStateAction<BadWords[]>>) => {
const getBadWords = async () => {
try {
const res = await client.get('/api/bad-words');
setBadWords(res.data.data);
if (!res) throw new Error('금칙어 조회 도중 에러가 발생했습니다.');
console.log(res);
return res;
} catch (error) {
console.error(error);
}
Expand All @@ -63,14 +64,34 @@ const postBadWords = async (badWordsRequest: BadWords) => {
};

// 내 상상대로 만든 필터링 단어 취소 버튼
const patchBadWords = async (badWordId: number) => {
const patchBadWordsUsed = async (badWordId: string) => {
try {
const res = await client.patch(`/api/bad-words/${badWordId}/status`, { isUsed: false });
if (!res) throw new Error('검열 단어 삭제 도중 에러가 발생했습니다.');
console.log(res);
return res;
} catch (error) {
console.error(error);
}
};

const patchBadWords = async (badWordId: string, word: string) => {
try {
const res = await client.patch(`/api/bad-words/${badWordId}`, { word: word });
if (!res) throw new Error('검열 단어 삭제 도중 에러가 발생했습니다.');
console.log(res);
return res;
} catch (error) {
console.error(error);
}
};

export { postReports, getReports, patchReport, getBadWords, postBadWords, patchBadWords };
export {
postReports,
getReports,
patchReport,
getBadWords,
postBadWords,
patchBadWordsUsed,
patchBadWords,
};
12 changes: 10 additions & 2 deletions src/apis/share.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ export const postSharePostLike = async (sharePostId: string) => {
return response.data;
} catch (error) {
console.error('❌ 편지 좋아요 중 에러가 발생했습니다', error);
throw new Error('편지 좋아요 실패');
}
};

Expand All @@ -175,6 +174,15 @@ export const getSharePostLikeCount = async (sharePostId: string) => {
return response.data;
} catch (error) {
console.error('❌ 편지 좋아요 갯수 조회 중 에러가 발생했습니다', error);
throw new Error('편지 좋아요 갯수 조회 실패');
}
};

export const deleteSharePost = async (sharePostId: string) => {
try {
const response = await client.delete(`/api/share-posts/${sharePostId}`);
if (!response) throw new Error('error while deleting post');
return response;
} catch (error) {
console.error('❌ 편지 삭제 중 에러가 발생했습니다', error);
}
};
17 changes: 16 additions & 1 deletion src/apis/write.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ const postLetter = async (data: LetterRequest) => {
if (!res) throw new Error('편지 전송과정에서 오류가 발생했습니다.');
return res;
} catch (error) {
const errorWithStatus = error as unknown as { status: number };
console.error(error);
return errorWithStatus;
}
};

Expand Down Expand Up @@ -42,4 +44,17 @@ const postTemporarySave = async (data: TemporaryRequest) => {
}
};

export { postLetter, postFirstReply, getPrevLetter, postTemporarySave };
const postTemporaryLetter = async (data: TemporaryRequest) => {
console.log('Temporary request', data);
try {
const res = await client.post('/api/letters', data);
if (!res) throw new Error('편지 전송과정에서 오류가 발생했습니다.');
return res;
} catch (error) {
const errorWithStatus = error as unknown as { status: number };
console.error(error);
return errorWithStatus;
}
};

export { postLetter, postFirstReply, getPrevLetter, postTemporarySave, postTemporaryLetter };
4 changes: 4 additions & 0 deletions src/assets/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import SnowIcon from './snow.svg?react';
import StampIcon from './stamp.svg?react';
import ThermostatIcon from './thermostat.svg?react';
import WarmIcon from './warm.svg?react';
import ToggleOff from './toggle-off.svg?react';
import ToggleOn from './toggle-on.svg?react';

export {
AddIcon,
Expand Down Expand Up @@ -54,4 +56,6 @@ export {
DeleteIcon,
CancelIcon,
PencilIcon,
ToggleOff,
ToggleOn,
};
3 changes: 3 additions & 0 deletions src/assets/icons/toggle-off.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/toggle-on.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/background-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/field-4-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/field-theme-asset-bird-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/home-left-mountain-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/landing-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 6 additions & 2 deletions src/components/BackgroundBottom.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import BgItem from '@/assets/images/field-4.png';
import BgItemDark from '@/assets/images/field-4-dark.png';

import BackgroundImageWrapper from './BackgroundImageWrapper';
import useThemeStore from '@/stores/themeStore';

const BackgroundBottom = () => {
const theme = useThemeStore((state) => state.theme);

return (
<BackgroundImageWrapper
as="div"
className="fixed bottom-[-40px] left-1/2 h-42 w-full -translate-x-1/2 opacity-70"
imageUrl={BgItem}
className="fixed bottom-[-40px] left-1/2 z-[-10] h-42 w-full -translate-x-1/2 opacity-70"
imageUrl={theme === 'light' ? BgItem : BgItemDark}
/>
);
};
Expand Down
26 changes: 15 additions & 11 deletions src/components/MenuButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,44 +16,48 @@ export default function MenuButton() {
<Link
to="/letter/box"
className={twMerge(
'bg-primary-3 fixed bottom-[220px] z-50 h-12 w-12 rotate-360 content-center rounded-full text-white transition-all duration-200 hover:scale-105 active:scale-90',
'bg-primary-3 fixed bottom-[220px] z-30 flex h-12 w-12 rotate-360 content-center items-center justify-center rounded-full text-white transition-all duration-200 hover:scale-105 active:scale-90',
isOpen
? 'translate-y-0 rotate-0 opacity-100'
: 'translate-y-[120%] rotate-180 opacity-0',
: 'pointer-events-none translate-y-[120%] rotate-180 opacity-0',
)}
onClick={() => setIsOpen(false)}
>
<MarkunreadOutlinedIcon fontSize="small" onClick={() => setIsOpen(false)} />
<MarkunreadOutlinedIcon fontSize="small" />
</Link>
<Link
to="/board/letter"
className={twMerge(
'bg-primary-3 fixed bottom-[160px] z-50 h-12 w-12 rotate-360 content-center rounded-full text-white transition-all duration-200 hover:scale-105 active:scale-90',
'bg-primary-3 fixed bottom-[160px] z-30 flex h-12 w-12 rotate-360 content-center items-center justify-center rounded-full text-white transition-all duration-200 hover:scale-105 active:scale-90',
isOpen
? 'translate-y-0 rotate-0 opacity-100'
: 'translate-y-[120%] rotate-180 opacity-0',
: 'pointer-events-none translate-y-[120%] rotate-180 opacity-0',
)}
onClick={() => setIsOpen(false)}
>
<CalendarTodayOutlinedIcon fontSize="small" onClick={() => setIsOpen(false)} />
<CalendarTodayOutlinedIcon fontSize="small" />
</Link>
<Link
to="/letter/write"
className={twMerge(
'bg-primary-3 fixed bottom-[100px] z-50 h-12 w-12 rotate-360 content-center rounded-full text-white transition-all duration-200 hover:scale-105 active:scale-90',
'bg-primary-3 fixed bottom-[100px] z-30 flex h-12 w-12 rotate-360 content-center items-center justify-center rounded-full text-white transition-all duration-200 hover:scale-105 active:scale-90',
isOpen
? 'translate-y-0 rotate-0 opacity-100'
: 'translate-y-[120%] rotate-180 opacity-0',
: 'pointer-events-none translate-y-[120%] rotate-180 opacity-0',
)}
onClick={() => setIsOpen(false)}
>
<EditNoteRoundedIcon fontSize="medium" onClick={() => setIsOpen(false)} />
<EditNoteRoundedIcon fontSize="medium" />
</Link>

<div
className={twMerge(
'bg-primary-3 fixed bottom-[30px] z-50 h-13 w-13 content-center rounded-full text-white transition-all duration-200 hover:scale-105 active:scale-90',
'bg-primary-3 fixed bottom-[30px] z-30 flex h-13 w-13 content-center items-center justify-center rounded-full text-white transition-all duration-200 hover:scale-105 active:scale-90',
isOpen ? 'rotate-90' : 'rotate-0',
)}
onClick={() => setIsOpen((state) => !state)}
>
<MenuRoundedIcon onClick={() => setIsOpen((state) => !state)} />
<MenuRoundedIcon />
</div>
</div>
</>
Expand Down
6 changes: 3 additions & 3 deletions src/components/NoticeRollingPaper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ const NoticeRollingPaper = () => {
<Link to={`/board/rolling/${data?.eventPostId}`}>
<article
className={twMerge(
'text-gray-60 flex w-full items-center gap-2.5 rounded-lg px-4 py-2',
'text-gray-60 flex w-full items-center gap-2.5 rounded-lg px-4 py-2 dark:text-white',
'bg-linear-[275deg,rgba(255,255,255,0.4)_13.74%,rgba(238,238,238,0.4)_67.61%]',
'shadow-[0_1px_6px_rgba(218,189,74,0.8)]',
'shadow-[0_1px_6px_rgba(218,189,74,0.8)] dark:shadow-[0_1px_6px_rgba(255,255,255,0.8)]',
)}
>
<NoticeIcon className="h-6 w-6 shrink-0 text-gray-50" />
<NoticeIcon className="h-6 w-6 shrink-0 text-gray-50 dark:text-white" />
<div ref={containerRef} className="w-full overflow-hidden whitespace-nowrap">
<p
ref={textRef}
Expand Down
2 changes: 1 addition & 1 deletion src/components/PageTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface PageTitleProps {

const PageTitle = ({ className, children }: PageTitleProps) => {
return (
<h1 className={twMerge('text-gray-60 body-b w-fit rounded-full bg-white px-6 py-4', className)}>
<h1 className={twMerge('text-gray-60 body-b w-fit rounded-full bg-white px-6 py-4 dark:shadow-[0_0px_10px_rgba(255,255,255,0.8)]', className)}>
{children}
</h1>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/ToastItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function ToastItem({ toastObj, index }: { toastObj: ToastObj; ind

const TOAST_POSITION = {
Top: 'top-20',
Bottom: 'bottom-5',
Bottom: 'bottom-20',
};

const animation = `toast-blink ${toastObj.time}s ease-in-out forwards`;
Expand Down
2 changes: 0 additions & 2 deletions src/hooks/useServerSentEvents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export const useServerSentEvents = () => {
const navigate = useNavigate();
// const recallCountRef = useRef(1);


const accessToken = useAuthStore((state) => state.accessToken);
const setAccessToken = useAuthStore((state) => state.setAccessToken);
const sourceRef = useRef<EventSourcePolyfill | null>(null);
Expand Down Expand Up @@ -93,7 +92,6 @@ export const useServerSentEvents = () => {
};
} catch (error) {
console.log('catch문에서 에러 발생', error);

}
};

Expand Down
11 changes: 11 additions & 0 deletions src/layouts/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@ import { Link, useNavigate } from 'react-router';

import { ArrowLeftIcon, PersonIcon } from '@/assets/icons';
import NotificationButton from '@/components/NotificationButton';
import FlareRoundedIcon from '@mui/icons-material/FlareRounded';
import DarkModeOutlinedIcon from '@mui/icons-material/DarkModeOutlined';
import useThemeStore from '@/stores/themeStore';

const Header = () => {
const theme = useThemeStore((state) => state.theme);
const toggleTheme = useThemeStore((state) => state.toggleTheme);

const navigate = useNavigate();

return (
Expand All @@ -12,6 +18,11 @@ const Header = () => {
<ArrowLeftIcon className="h-6 w-6 text-white" />
</button>
<div className="flex items-center gap-3">
{theme === 'light' ? (
<FlareRoundedIcon className="h-6 w-6 text-white" onClick={toggleTheme} />
) : (
<DarkModeOutlinedIcon className="h-6 w-6 text-white" onClick={toggleTheme} />
)}
<NotificationButton />
<Link to="/mypage">
<PersonIcon className="h-6 w-6 text-white" />
Expand Down
2 changes: 1 addition & 1 deletion src/layouts/MobileLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Outlet } from 'react-router';
const MobileLayout = () => {
return (
<div className="mobile-bg">
<div className="mobile-layout">
<div className="mobile-layout z-2">
<Outlet />
</div>
</div>
Expand Down
16 changes: 8 additions & 8 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { StrictMode } from 'react';
// import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router';

Expand All @@ -15,11 +15,11 @@ queryClient.setDefaultOptions({
});

createRoot(document.getElementById('root')!).render(
<StrictMode>
<QueryClientProvider client={queryClient}>
<BrowserRouter>
<App />
</BrowserRouter>
</QueryClientProvider>
</StrictMode>,
// <StrictMode>
<QueryClientProvider client={queryClient}>
<BrowserRouter>
<App />
</BrowserRouter>
</QueryClientProvider>,
// </StrictMode>,
);
Loading