Skip to content

Commit

Permalink
Merge pull request #20 from Funssion-SWM/temporary-store
Browse files Browse the repository at this point in the history
Temporary store
  • Loading branch information
dongree authored Aug 29, 2023
2 parents e843511 + db9e8ae commit a0dc865
Show file tree
Hide file tree
Showing 13 changed files with 191 additions and 18 deletions.
23 changes: 23 additions & 0 deletions src/app/me/[slug]/drafts/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Header from '@/components/shared/Header';
import { getMemosDraftsByUserId } from '@/service/me';
import LayoutWrapper from '@/components/shared/LayoutWrapper';
import MeDraftContainer from '@/components/me/MeDraftContainer';

type Props = {
params: {
slug: number;
};
};

export default async function MeDraftPage({ params: { slug } }: Props) {
const memos = await getMemosDraftsByUserId(slug);

return (
<section>
<Header />
<LayoutWrapper paddingY="sm:py-5">
<MeDraftContainer memos={memos} />
</LayoutWrapper>
</section>
);
}
47 changes: 36 additions & 11 deletions src/components/create/memo/EditorForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import { useEditor } from '@tiptap/react';
import { useRouter } from 'next/navigation';
import { useContext, useEffect, useRef, useState } from 'react';
import BlueBtn from '../../shared/btn/BlueBtn';
import { createOrUpdateMemo } from '@/service/memos';
import { createOrUpdateMemo, getMemoDrafts } from '@/service/memos';
import { getPrevText } from '@/lib/editor';
import { useCompletion } from 'ai/react';
import { getDescription } from '@/service/description';
import { ModalContext } from '@/context/ModalProvider';
import { TiptapExtensions } from '@/components/editor/extensions';
import { TiptapEditorProps } from '@/components/editor/props';
import { MemoColor } from '@/types/memo';
import { Memo, MemoColor } from '@/types/memo';
import BlueBtnWithCount from '@/components/shared/btn/BlueBtnWithCount';

type Props = {
preTitle?: string;
Expand Down Expand Up @@ -122,9 +123,19 @@ export default function EditorForm({
};
}, [stop, isLoading, editor, complete, completion.length]);

const [memos, setMemos] = useState<Memo[]>([]);
const [title, setTitle] = useState(preTitle);
const [selectedColor, setSelectedColor] = useState<MemoColor>(preColor);
const handleBtnClick = () => {

const first = async () => {
getMemoDrafts().then((data) => setMemos(data));
}

useEffect(() => {
first();
}, [])

const save = (saveMode:string) => {
if (title === '') {
alert('제목을 작성해주세요!');
return;
Expand Down Expand Up @@ -152,19 +163,23 @@ export default function EditorForm({
memoDescription,
memoText,
memoColor: selectedColor,
isTemporary: saveMode=="temporary",
}
).then(() => {
if (alreadyExists) router.push('/memos');
else router.push(`/memos/${memoId}`);
router.refresh();
});
};
}

const handleBtnClickSave = () => save("permanent");
const handleBtnClickTemporalSave = () => save("temporary");

const handleColorClick = (color: MemoColor) => setSelectedColor(color);

return (
<section
className={`relative flex flex-col rounded-lg shadow-lg px-4 py-2 min-h-screen sm:min-h-[calc(100vh-100px)] ${
className={`relative flex flex-col rounded-lg shadow-lg px-4 py-2 min-h-screen sm:min-h-[calc(100vh-100px)] ${
{
yellow: 'bg-memo-yellow',
green: 'bg-memo-green',
Expand All @@ -176,11 +191,21 @@ export default function EditorForm({
}[selectedColor]
}`}
>
<BlueBtn
text={alreadyExists ? '등록' : '수정'}
onClick={handleBtnClick}
extraStyle="self-end"
/>
<div className='text-right'>
<BlueBtnWithCount
text='임시저장'
count={memos.length}
onClickBtn={handleBtnClickTemporalSave}
onClickCount={() =>
open("임시 저장된 글", () => {router.refresh()} , "draft", memos)
}
extraStyle={`mr-2 ${alreadyExists?"visible":"hidden"}`}
/>
<BlueBtn
text={alreadyExists ? '등록' : '수정'}
onClick={handleBtnClickSave}
/>
</div>
<input
type="text"
placeholder="제목을 입력해주세요."
Expand All @@ -197,7 +222,7 @@ export default function EditorForm({
className="absolute bottom-3 right-5 text-soma-grey-50"
onClick={() =>
open('나가시겠습니까?', () => {
router.back();
router.push(`/memos`);
})
}
>
Expand Down
26 changes: 26 additions & 0 deletions src/components/me/MeDraftContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use client';

import { Memo } from '@/types/memo';
import MemosGrid from '@/components/memo/MemosGrid'
import CategoryBtn from '@/components/shared/btn/CategoryBtn';
// import CategoryBtn from '../shared/btn/CategoryBtn';

type Props = {
memos: Memo[];
};

export default function MeDraftContainer({ memos }: Props) {

return (
<div>
<div className="flex gap-2 mb-5">
<CategoryBtn
text="Memo"
onClick={() => {}}
isSelected={true}
/>
</div>
<MemosGrid memos={memos} colNum={4} />
</div>
);
}
5 changes: 4 additions & 1 deletion src/components/memo/MemoCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default function MemoCard({
authorName,
authorProfileImagePath,
likes,
isTemporary,
},
}: Props) {
return (
Expand All @@ -40,7 +41,9 @@ export default function MemoCard({
imagePath={authorProfileImagePath}
authorId={authorId}
/>
<Link href={`/memos/${memoId}`}>
<Link href={isTemporary ?
`/create/memo/${memoId}` :
`/memos/${memoId}`}>
<h2 className="text-2xl font-bold my-5 line-clamp-2 break-all">
{memoTitle}
</h2>
Expand Down
1 change: 1 addition & 0 deletions src/components/memo/MemoViewerHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export default function MemoViewerHeader({ memoId, authorId, likes }: Props) {
onClick={() => {
setIsActive(false);
router.push(`/create/memo/${memoId}`);
router.refresh();
}}
>
수정하기
Expand Down
1 change: 1 addition & 0 deletions src/components/memo/MemosGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default function MemosGrid({ memos, colNum }: Props) {
className={`grid gap-4 grid-cols-1
${
{
2: 'lg:grid-cols-2',
3: 'md:grid-cols-2 lg:grid-cols-3',
4: 'sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4',
}[colNum]
Expand Down
9 changes: 9 additions & 0 deletions src/components/shared/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ export default function Header() {
>
프로필
</button>
<button
className="hover:bg-gray-200 p-2 rounded-t-lg"
onClick={() => {
checkUser().then((data) => router.push(`/me/${data.id}/drafts`));
setIsActive(false);
}}
>
임시 글
</button>
<button
className="hover:bg-gray-200 p-2 rounded-b-lg"
onClick={() => {
Expand Down
22 changes: 19 additions & 3 deletions src/components/shared/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import { ModalContext } from '@/context/ModalProvider';
import { useContext } from 'react';
import BlueBtn from './btn/BlueBtn';
import BlueBtn2 from './btn/BlueBtn2';
import MemosGrid from '../memo/MemosGrid';
import { Memo } from '@/types/memo';

export default function Modal() {
const { isOpen, close, onSuccess, modalText } = useContext(ModalContext);
const { isOpen, mode, memos, close, onSuccess, modalText } = useContext(ModalContext);

return (
isOpen && (
(isOpen && mode =='' && (
<div className="fixed">
<Overay onClick={() => close()} />
<div
Expand All @@ -29,7 +31,21 @@ export default function Modal() {
</div>
</div>
</div>
)
)) ||
(isOpen && mode == 'draft' && (
<div className='fixed'>
<Overay onClick={() => close()} />
<div
className="fixed flex flex-col items-center bg-white rounded-2xl p-5 sm:p-10 w-1/2 h-3/4 overflow-scroll
top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 gap-2 "
>
<p className="sm:text-lg">{modalText}</p>
<div className="flex gap-2" onClick={close}>
<MemosGrid memos={memos} colNum={2} />
</div>
</div>
</div>
))
);
}

Expand Down
29 changes: 29 additions & 0 deletions src/components/shared/btn/BlueBtnWithCount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
type Props = {
text: string;
count?: number;
onClickBtn: () => void;
onClickCount: () => void;
extraStyle?: string;
};

export default function BlueBtnWithCount({ text, count = 0, onClickBtn, onClickCount, extraStyle = '' }: Props) {
return (
<span className={extraStyle}>
<button
type="button"
className={`bg-soma-blue-40 text-white pl-3.5 pr-2 py-2 rounded-l-3xl transition hover:bg-soma-blue-50 text-sm sm:text-base`}
onClick={() => onClickBtn()}
>
{text}
</button>
<button
type="button"
className={`bg-soma-blue-40 text-white pr-3.5 pl-2 py-2 rounded-r-3xl transition hover:bg-soma-blue-50 text-sm sm:text-base`}
onClick={() => onClickCount()}
>
{count}
</button>
</span>
);
}

15 changes: 12 additions & 3 deletions src/context/ModalProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use client';

import { Memo } from '@/types/memo';
import { ReactNode, createContext, useState } from 'react';

type Props = {
Expand All @@ -8,12 +9,16 @@ type Props = {

export const ModalContext = createContext<{
isOpen: boolean;
open: (text: string, onSuccess: () => void) => void;
mode: string;
memos: Memo[];
open: (text: string, onSuccess: () => void, mode?: string, memos?: Memo[]) => void;
close: () => void;
modalText: string;
onSuccess: () => void;
}>({
isOpen: false,
mode: '',
memos: [],
open: () => {},
close: () => {},
modalText: '',
Expand All @@ -22,12 +27,16 @@ export const ModalContext = createContext<{

export default function ModalProvider({ children }: Props) {
const [isOpen, setIsOpen] = useState(false);
const [mode, setMode] = useState('');
const [memos, setMemos] = useState<Memo[]>([]);
const [modalText, setModalText] = useState('');
const [onSuccess, setOnSuccess] = useState<() => void>(() => {});

const open = (text: string, callback: () => void) => {
const open = (text: string, callback: () => void, mode?: string, memos?: Memo[]) => {
setIsOpen(true);
setModalText(text);
setMode(mode ? mode : '');
setMemos(memos ? memos : []);
setOnSuccess(() => {
return callback;
});
Expand All @@ -41,7 +50,7 @@ export default function ModalProvider({ children }: Props) {

return (
<ModalContext.Provider
value={{ isOpen, open, close, modalText, onSuccess }}
value={{ isOpen, mode, memos, open, close, modalText, onSuccess }}
>
{children}
</ModalContext.Provider>
Expand Down
14 changes: 14 additions & 0 deletions src/service/me.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@ export async function getMemosByUserId(userId: number): Promise<Memo[]> {
.catch(console.error);
}

export async function getMemosDraftsByUserId(userId: number): Promise<Memo[]> {
return fetch(
`${process.env.NEXT_PUBLIC_SERVER_IP_ADDRESS}/mypage/${userId}/memos/drafts`,
{
next: { revalidate: 0 },
}
)
.then((res) => {
if (!res.ok) throw new Error('error 발생!');
return res.json();
})
.catch(console.error);
}

export async function getLikedMemosByUserId(userId: number): Promise<Memo[]> {
return fetch(
`${process.env.NEXT_PUBLIC_SERVER_IP_ADDRESS}/mypage/${userId}/memos/liked`,
Expand Down
15 changes: 15 additions & 0 deletions src/service/memos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ export async function getMemos(
.catch(console.error);
}

export async function getMemoDrafts(): Promise<Memo[]> {
return fetch(
`${process.env.NEXT_PUBLIC_SERVER_IP_ADDRESS}/memos/drafts`,
{
next: { revalidate: 0 },
credentials: 'include',
}
)
.then((res) => {
if (!res.ok) throw new Error('error 발생!');
return res.json();
})
.catch(console.error);
}

export async function getMemoById(id: number): Promise<Memo> {
return fetch(`${process.env.NEXT_PUBLIC_SERVER_IP_ADDRESS}/memos/${id}`, {
next: { revalidate: 0 },
Expand Down
2 changes: 2 additions & 0 deletions src/types/memo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ export type Memo = {
authorName: string;
authorProfileImagePath: string;
likes: number;
isTemporary: boolean;
};

export type PostMemoData = {
memoTitle: string;
memoDescription: string;
memoText: string;
memoColor: string;
isTemporary ?: boolean;
};

export type MemoColor =
Expand Down

0 comments on commit a0dc865

Please sign in to comment.