diff --git a/pages/main/index.tsx b/pages/main/index.tsx index d59855ff..48a5d16d 100644 --- a/pages/main/index.tsx +++ b/pages/main/index.tsx @@ -1,19 +1,10 @@ import { useRouter, useSearchParams } from 'next/navigation'; -import { useEffect, useRef } from 'react'; -import WriteInput from '@components/Input/WriteInput'; import Layout from '@components/Layout'; import MainPageTab from '@components/Layout/MainPageTab'; import { ROUTES } from '@constants/routes'; -import WriteGuide from '@domain/끄적이는/components/Guide'; -import TemporalMemoHistoryTable from '@domain/끄적이는/components/History'; -import TodayTemoralMemos from '@domain/끄적이는/components/Today'; -import useCreateTemporalMemo from '@domain/끄적이는/mutations/useCreateTemporalMemo'; -import useGetWriteHistory from '@domain/끄적이는/queries/useGetHistory'; -import * as styles from '@domain/끄적이는/style.css'; +import WriteTabContent from '@domain/끄적이는/components/WriteTabContent'; import 참고하는TabContent from '@domain/참고하는/components'; -import { useInput } from '@hooks/useInput'; -import useGetMemoFolders from '@queries/useGetMemoFolders'; import useGetMyProfile from '@queries/useGetMyProfile'; import { COLORS } from '@styles/tokens'; @@ -21,61 +12,21 @@ const MainPage = () => { const router = useRouter(); const searchParams = useSearchParams(); - useGetMyProfile(); - - const writeContentRef = useRef(null); - const writeInput = useInput({ id: 'write-input' }); - const { todayMemos, history } = useGetWriteHistory(); - const { mutate: submitTemporalMemo } = useCreateTemporalMemo(); - const { data: memoFolders } = useGetMemoFolders(); - const selectedTab = searchParams.get('tab') || 'write'; - useEffect(() => { - handleScroll(); - }, [todayMemos]); - - const handleScroll = () => { - if (writeContentRef.current) { - writeContentRef.current.scrollTop = writeContentRef.current.scrollHeight; - } - }; + useGetMyProfile(); const handleTabSelect = (selectedTab: string) => { router.push(`${ROUTES.MAIN}?tab=${selectedTab}`); }; - const handleSubmit = () => { - submitTemporalMemo(writeInput.value); - writeInput.reset(); - - handleScroll(); - }; - const backgroundColor = selectedTab === 'refer' ? COLORS['Grey/100'] : undefined; return ( -
- - - -
- -
-
- - } + write={} refer={<참고하는TabContent />} selectedTab={selectedTab} handleTabSelect={handleTabSelect} diff --git a/src/assets/icons/smileFace.svg b/src/assets/icons/smileFace.svg index c0d694b4..04a1f4d9 100644 --- a/src/assets/icons/smileFace.svg +++ b/src/assets/icons/smileFace.svg @@ -1,4 +1,4 @@ - + diff --git a/src/assets/images/message.svg b/src/assets/images/message.svg new file mode 100644 index 00000000..61a5c36e --- /dev/null +++ b/src/assets/images/message.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/components/DayMessage/index.tsx b/src/components/DayMessage/index.tsx new file mode 100644 index 00000000..5060f842 --- /dev/null +++ b/src/components/DayMessage/index.tsx @@ -0,0 +1,23 @@ +import { type PropsWithChildren } from 'react'; + +import Icon from '@components/Icon'; +import { type Icons } from '@constants/icon'; + +import * as styles from './style.css'; + +interface DayMessageProps { + icon?: Icons; +} + +const DayMessage = ({ children, icon }: PropsWithChildren) => { + return ( +
+
+ {icon && } + {children} +
+
+ ); +}; + +export default DayMessage; diff --git a/src/components/DayMessage/style.css.ts b/src/components/DayMessage/style.css.ts new file mode 100644 index 00000000..5f71d90f --- /dev/null +++ b/src/components/DayMessage/style.css.ts @@ -0,0 +1,29 @@ +import { style } from '@vanilla-extract/css'; + +import { sprinkles } from '@styles/sprinkles.css'; +import { COLORS } from '@styles/tokens'; +import * as utils from '@styles/utils.css'; + +export const wrapper = style([ + utils.flexCenter, + { + marginTop: '12px', + marginBottom: '24px', + }, +]); + +export const message = style([ + utils.flexCenter, + { + padding: '6px 28px', + border: `1px solid ${COLORS['Grey/200']}`, + borderRadius: '100px', + }, +]); + +export const text = style([ + sprinkles({ typography: '15/Body/Medium' }), + { + marginLeft: '6px', + }, +]); diff --git a/src/components/Dropdown/FolderDropdown/index.tsx b/src/components/Dropdown/FolderDropdown/index.tsx index 1424fb88..b8d299bc 100644 --- a/src/components/Dropdown/FolderDropdown/index.tsx +++ b/src/components/Dropdown/FolderDropdown/index.tsx @@ -1,4 +1,5 @@ import { type Folder } from '@api/memoFolder/types'; +import Button from '@components/Button'; import TooltipButton from '@components/Button/components/TooltipButton'; import Dropdown from '@components/Dropdown'; import Icon from '@components/Icon'; @@ -29,12 +30,9 @@ const FolderDropdown = ({ return ( <> {onClickBookmark ? ( - + ) : ( )} diff --git "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Card/Today/index.tsx" "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Card/Today/index.tsx" index b773e5fd..1fd5a7b4 100644 --- "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Card/Today/index.tsx" +++ "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Card/Today/index.tsx" @@ -49,11 +49,8 @@ const WriteTodayCard = ({ const [spellCheckResult, setSpellCheckResult] = useState(); - const { - mutateAsync: spellCheck, - isPending: isPendingSpellCheck, - isSuccess: isSuccessSpellCheck, - } = usePostSpellCheck(); + const { mutateAsync: spellCheck, isPending: isPendingSpellCheck } = + usePostSpellCheck(); const handleSpellCheck = async () => { const spellCheckResult = await spellCheck({ @@ -97,7 +94,7 @@ const WriteTodayCard = ({ return ( - {!isSuccessSpellCheck && ( + {!spellCheckResult?.result.suggestions.length && ( { +const EXAMPLE_CARD = [ + { + title: '자료 확인 요청', + description: + '안녕하세요, 바로님. 현재 baro 추천 상품 팝업 프로젝트에 대한 세부 기획 작업 진행 중입니다. 관련하여 첨부된 pdf 파일을 차주 목요일까지 확인 후 피드백 주시면 프로젝트 진행에 큰 도움이 될 것 같습니다. 감사합니다.', + }, + { + title: '권한 요청', + description: + '안녕하세요, 바로님. 다름이 아니라 업무 진행을 위해 JIRA 권한을 받고자 하는데 시간 괜찮으실 때 권한 추가해 주실 수 있을까요?', + }, + { + title: '일정 참석 요청', + description: + '바로님, 최종으로 업무 산출물 공유 드리기 전에 여쭤보고 싶은 마이너한 부분들이 있습니다. 혹시 시간 괜찮으실 때 논의 가능하실까요?', + }, +]; + +interface GuideProps { + hasMemo: boolean; +} + +const Guide = ({ hasMemo }: GuideProps) => { return ( -

- 끄적인 글은 일주일 후에 사라져요! 오래 간직하고 싶다면 저장해주세요 😊 -

+ <> + {hasMemo ? ( +

+ + 끄적인 글은 일주일 후에 사라져요! 오래 간직하고 싶다면 저장해주세요 + + +

+ ) : ( +
+
+ +
+ 끄적이는 예시 + + {EXAMPLE_CARD.map(({ title, description }) => ( + + {title} + {description} + + ))} + +
+ )} + ); }; -export default WriteGuide; +export default Guide; diff --git "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Guide/style.css.ts" "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Guide/style.css.ts" index 8f5f2323..b56332e6 100644 --- "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Guide/style.css.ts" +++ "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Guide/style.css.ts" @@ -1,12 +1,32 @@ import { style } from '@vanilla-extract/css'; +import { sprinkles } from '@styles/sprinkles.css'; import { COLORS } from '@styles/tokens'; +import * as utils from '@styles/utils.css'; -export const guideText = style({ - marginTop: '220px', - marginBottom: '12px', - color: COLORS['Grey/500'], - textAlign: 'center', - fontSize: '15px', - fontWeight: '500', +export const guide = style([ + utils.flexCenter, + { + marginTop: '220px', + marginBottom: '12px', + gap: '2px', + }, +]); + +export const guideText = style([ + sprinkles({ typography: '15/Title/Medium' }), + { + color: COLORS['Grey/500'], + }, +]); + +export const newMemberGuide = style({ + marginBottom: '48px', +}); + +export const guideImage = style({ + display: 'flex', + justifyContent: 'center', + marginTop: '240px', + marginBottom: '64px', }); diff --git "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/History/index.css.ts" "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/History/index.css.ts" index baf8464d..7d0b2d6a 100644 --- "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/History/index.css.ts" +++ "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/History/index.css.ts" @@ -1,36 +1,8 @@ import { style } from '@vanilla-extract/css'; -import { COLORS } from '@styles/tokens'; - export const container = style({ marginBottom: '48px', display: 'flex', flexDirection: 'column', gap: '64px', }); - -export const dateLabelWrapper = style({ - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - marginTop: '12px', - marginBottom: '24px', -}); - -export const dateLabel = style({ - padding: '6px 28px', - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - border: `1px solid ${COLORS['Grey/200']}`, - borderRadius: '100px', -}); - -export const dateLabelText = style({ - marginLeft: '6px', - color: COLORS['Grey/700'], - fontSize: '15px', - fontWeight: 500, - lineHeight: '24px', - letterSpacing: '-0.2px', -}); diff --git "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/History/index.tsx" "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/History/index.tsx" index 2983bafd..23e6cac0 100644 --- "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/History/index.tsx" +++ "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/History/index.tsx" @@ -4,7 +4,7 @@ import dayjs from 'dayjs'; import 'dayjs/locale/ko'; import { type Folder } from '@api/memoFolder/types'; -import Icon from '@components/Icon'; +import DayMessage from '@components/DayMessage'; import Responsive from '@components/Responsive'; import { type TemporalMemoHistory } from '../../types'; @@ -23,36 +23,31 @@ const TemporalMemoHistoryTable = ({ const [editModeCardId, setEditModeCardId] = useState(null); return ( -
- {data.map((hisotry, i) => { - const { createdAt: createAt, temporalMemos } = hisotry; - - return ( -
-
-
- - - {dayjs(createAt).locale('ko').format('YYYY.MM.DD (dd)')} - -
-
- - {temporalMemos.map((temporalMemo) => ( - setEditModeCardId(temporalMemo.id)} - onEditCompleteClick={() => setEditModeCardId(null)} - /> - ))} - -
- ); - })} -
+ <> + {!!data.length && ( +
+ {data.map(({ createdAt, temporalMemos }, i) => ( +
+ + {dayjs(createdAt).locale('ko').format('YYYY.MM.DD (dd)')} + + + {temporalMemos.map((temporalMemo) => ( + setEditModeCardId(temporalMemo.id)} + onEditCompleteClick={() => setEditModeCardId(null)} + /> + ))} + +
+ ))} +
+ )} + ); }; diff --git "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Today/index.css.ts" "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Today/index.css.ts" index a22dbcee..c4634fa8 100644 --- "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Today/index.css.ts" +++ "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Today/index.css.ts" @@ -1,36 +1,8 @@ import { style } from '@vanilla-extract/css'; -import { COLORS } from '@styles/tokens'; - export const container = style({ display: 'flex', flexDirection: 'column', gap: '20px', marginBottom: '40px', }); - -export const dateLabelWrapper = style({ - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - marginTop: '12px', - marginBottom: '24px', -}); - -export const dateLabel = style({ - padding: '6px 28px', - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - border: `1px solid ${COLORS['Grey/200']}`, - borderRadius: '100px', -}); - -export const dateLabelText = style({ - marginLeft: '6px', - color: COLORS['Grey/700'], - fontSize: '15px', - fontWeight: 500, - lineHeight: '24px', - letterSpacing: '-0.2px', -}); diff --git "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Today/index.tsx" "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Today/index.tsx" index d8075248..08b15a10 100644 --- "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Today/index.tsx" +++ "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/Today/index.tsx" @@ -1,7 +1,7 @@ import { useState } from 'react'; import { type Folder } from '@api/memoFolder/types'; -import Icon from '@components/Icon'; +import DayMessage from '@components/DayMessage'; import { type TemporalMemo } from '../../types'; import WriteTodayCard from '../Card/Today'; @@ -21,12 +21,7 @@ const TodayTemoralMemos = ({ memos, memoFolders }: TodayTemoralMemosProps) => { return (
-
-
- -

오늘 끄적인 문장

-
-
+ 오늘 끄적인 문장
    {memos.map((memo) => ( { + const writeContentRef = useRef(null); + const writeInput = useInput({ id: 'write-input' }); + + const { + data: { history, todayMemos }, + isLoading: isLoadingWriteHistory, + } = useGetWriteHistory(); + const { mutate: submitTemporalMemo } = useCreateTemporalMemo(); + const { data: memoFolders } = useGetMemoFolders(); + + useEffect(() => { + handleScroll(); + }, [todayMemos]); + + const handleScroll = () => { + if (writeContentRef.current) { + writeContentRef.current.scrollTop = writeContentRef.current.scrollHeight; + } + }; + + const handleSubmit = () => { + submitTemporalMemo(writeInput.value); + writeInput.reset(); + + handleScroll(); + }; + + return ( +
    +
    + {!isLoadingWriteHistory && ( + + )} + + +
    + +
    +
    +
    + ); +}; + +export default WriteTabContent; diff --git "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/style.css.ts" "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/WriteTabContent/style.css.ts" similarity index 100% rename from "src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/style.css.ts" rename to "src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/components/WriteTabContent/style.css.ts" diff --git "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/mutations/useDeleteTemporalMemo.ts" "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/mutations/useDeleteTemporalMemo.ts" index 2d989dae..c7cbc711 100644 --- "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/mutations/useDeleteTemporalMemo.ts" +++ "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/mutations/useDeleteTemporalMemo.ts" @@ -1,6 +1,8 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; import { http } from '@api/http'; +import { TOAST_MESSAGE } from '@constants/toast'; +import { useToastStore } from '@stores/toast'; import { TemporalMemoQueryKeys } from '../constants/queryKeys'; @@ -9,11 +11,16 @@ const deleteTemporalMemo = async (id: number) => { }; const useDeleteTemporalMemo = () => { + const { showToast } = useToastStore(); + const queryClient = useQueryClient(); + return useMutation({ mutationFn: deleteTemporalMemo, onSuccess: () => { queryClient.invalidateQueries({ queryKey: TemporalMemoQueryKeys.all }); + + showToast({ message: TOAST_MESSAGE.CARD.DELETE }); }, }); }; diff --git "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/mutations/useEditTemporalMemo.ts" "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/mutations/useEditTemporalMemo.ts" index 4bd3f9cc..31c17627 100644 --- "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/mutations/useEditTemporalMemo.ts" +++ "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/mutations/useEditTemporalMemo.ts" @@ -1,6 +1,8 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; import { http } from '@api/http'; +import { TOAST_MESSAGE } from '@constants/toast'; +import { useToastStore } from '@stores/toast'; import { TemporalMemoQueryKeys } from '../constants/queryKeys'; @@ -15,12 +17,16 @@ const editTemporalMemo = async ({ }; const useEditTemporalMemo = () => { + const { showToast } = useToastStore(); + const queryClient = useQueryClient(); return useMutation({ mutationFn: editTemporalMemo, onSuccess: () => { queryClient.invalidateQueries({ queryKey: TemporalMemoQueryKeys.all }); + + showToast({ message: TOAST_MESSAGE.CARD.EDIT }); }, }); }; diff --git "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/mutations/useSaveTemporalMemo.ts" "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/mutations/useSaveTemporalMemo.ts" index 42822d96..2effb6d5 100644 --- "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/mutations/useSaveTemporalMemo.ts" +++ "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/mutations/useSaveTemporalMemo.ts" @@ -19,14 +19,15 @@ const saveTemporalMemo = async ({ }; const useSaveTemporalMemo = () => { - const queryClient = useQueryClient(); - const { showToast } = useToastStore(); + const queryClient = useQueryClient(); + return useMutation({ mutationFn: saveTemporalMemo, onSuccess: () => { queryClient.invalidateQueries({ queryKey: TemporalMemoQueryKeys.all }); + showToast({ message: TOAST_MESSAGE.CARD.SAVE }); }, }); diff --git "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/queries/useGetHistory.ts" "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/queries/useGetHistory.ts" index 9788e05f..c80c6f3c 100644 --- "a/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/queries/useGetHistory.ts" +++ "b/src/domain/\353\201\204\354\240\201\354\235\264\353\212\224/queries/useGetHistory.ts" @@ -6,6 +6,8 @@ import { http } from '@api/http'; import { TemporalMemoQueryKeys } from '../constants/queryKeys'; import { type TemporalMemoHistory } from '../types'; +const DATE_FORMAT = 'YYYY-MM-DD'; + export const getWriteHistory = async ({ startDate, endDate, @@ -21,33 +23,33 @@ export const getWriteHistory = async ({ }; const useGetWriteHistory = () => { - const endDate = dayjs().startOf('d').format('YYYY-MM-DD'); - const startDate = dayjs(endDate).subtract(7, 'd').format('YYYY-MM-DD'); + const endDate = dayjs().startOf('d').format(DATE_FORMAT); + const startDate = dayjs(endDate).subtract(7, 'd').format(DATE_FORMAT); - const { data } = useQuery({ + const { data, isLoading } = useQuery({ queryKey: TemporalMemoQueryKeys.getHistory(startDate, endDate), queryFn: () => getWriteHistory({ startDate, endDate }), select: (data) => { return { todayMemos: data.filter( (history) => - dayjs(history.createdAt).format('YYYY-MM-DD') === - dayjs().format('YYYY-MM-DD'), + dayjs(history.createdAt).format(DATE_FORMAT) === + dayjs().format(DATE_FORMAT), ), history: data .filter( (history) => - dayjs(history.createdAt).format('YYYY-MM-DD') !== - dayjs().format('YYYY-MM-DD'), + dayjs(history.createdAt).format(DATE_FORMAT) !== + dayjs().format(DATE_FORMAT), ) .reverse(), }; }, }); - if (!data) return { todayMemos: [], history: [] }; + if (!data) return { data: { todayMemos: [], history: [] }, isLoading: true }; - return data; + return { data, isLoading }; }; export default useGetWriteHistory; diff --git "a/src/domain/\354\240\200\354\236\245\355\225\230\353\212\224/mutations/useUpdateArchives.ts" "b/src/domain/\354\240\200\354\236\245\355\225\230\353\212\224/mutations/useUpdateArchives.ts" index 413ab102..a8bcd2e8 100644 --- "a/src/domain/\354\240\200\354\236\245\355\225\230\353\212\224/mutations/useUpdateArchives.ts" +++ "b/src/domain/\354\240\200\354\236\245\355\225\230\353\212\224/mutations/useUpdateArchives.ts" @@ -1,9 +1,14 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { TOAST_MESSAGE } from '@constants/toast'; +import { useToastStore } from '@stores/toast'; + import archiveApi from '../api'; import { ARCHIVES_QUERY_KEY } from '../constants/queryKeys'; const useUpdateArchives = (folderId: number) => { + const { showToast } = useToastStore(); + const queryClient = useQueryClient(); return useMutation({ @@ -12,6 +17,8 @@ const useUpdateArchives = (folderId: number) => { queryClient.invalidateQueries({ queryKey: ARCHIVES_QUERY_KEY.item([folderId]), }); + + showToast({ message: TOAST_MESSAGE.CARD.EDIT }); }, }); };