Skip to content

Commit c3a5dae

Browse files
authored
Feature: 메모 리스트 보는 방식을 추가한다 (#80)
* refactor: `MemoList`에서 `MemoTable`로 네이밍을 수정한다 * feat: MemoGrid를 구현한다 * feat: `@egjs/react-infinitegrid`를 설치한다 * feat: react-infinitegrid를 적용한다 * fix: 최대 개수 이슈를 해결한다 * design: gap과 너비를 넓힌다 * fix: 타입 에러를 해결한다 * design: 가운데 정렬하고, gap을 넓힌다
1 parent 1b75bf3 commit c3a5dae

File tree

7 files changed

+149
-5
lines changed

7 files changed

+149
-5
lines changed

packages/shared/src/types/supabaseCustom.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ import type { PostgrestSingleResponse, SupabaseClient } from '@supabase/supabase
22
import { Database } from './supabase';
33

44
export type MemoTable = Database['memo']['Tables']['memo'];
5+
export type MemoRow = Database['memo']['Tables']['memo']['Row'];
56
export type MemoSupabaseClient = SupabaseClient<Database, 'memo', Database['memo']>;
67
export type MemoSupabaseResponse = PostgrestSingleResponse<Array<MemoTable['Row']>>;

packages/web/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"start": "next start"
99
},
1010
"dependencies": {
11+
"@egjs/react-infinitegrid": "^4.12.0",
1112
"@extension/shared": "workspace:*",
1213
"@extension/storage": "workspace:*",
1314
"@extension/ui": "workspace:*",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
'use client';
2+
3+
import { useMemoListQuery } from '@extension/shared/hooks';
4+
5+
import { getSupabaseClient } from '@src/utils/supabase.client';
6+
import { UseQueryResult } from '@tanstack/react-query';
7+
import { MasonryInfiniteGrid } from '@egjs/react-infinitegrid';
8+
import { useEffect, useState } from 'react';
9+
10+
import { MemoRow, MemoSupabaseResponse } from '@extension/shared/types';
11+
import Link from 'next/link';
12+
13+
const Item = ({ num }: any) => (
14+
<div
15+
style={{
16+
width: '250px',
17+
}}>
18+
<div className="thumbnail">
19+
<img src={`https://naver.github.io/egjs-infinitegrid/assets/image/${(num % 33) + 1}.jpg`} alt="egjs" />
20+
</div>
21+
<div className="info">{`egjs ${num}`}</div>
22+
</div>
23+
);
24+
25+
function getItems(nextGroupKey: number, count: number) {
26+
const nextItems = [];
27+
const nextKey = nextGroupKey * 10;
28+
29+
for (let i = 0; i < count; ++i) {
30+
nextItems.push({ groupKey: nextGroupKey, key: nextKey + i });
31+
}
32+
return nextItems;
33+
}
34+
35+
export default function MemoGrid() {
36+
const supabaseClient = getSupabaseClient();
37+
// TODO :타입 에러로 인해 타입 단언으로 임시 해결
38+
const { data: memoListData }: UseQueryResult<MemoSupabaseResponse, Error> = useMemoListQuery({
39+
supabaseClient,
40+
});
41+
const memoList = memoListData?.data;
42+
const [items, setItems] = useState(() => getItems(0, 10));
43+
44+
if (!memoList || memoList.length === 0)
45+
return <p className="text-center mt-8">아직 저장된 메모가 없어요. 사이드 패널을 열어 메모를 저장해보세요 !</p>;
46+
return (
47+
<MasonryInfiniteGrid
48+
className="container"
49+
gap={16}
50+
align="center"
51+
onRequestAppend={e => {
52+
const nextGroupKey = (+e.groupKey! || 0) + 1;
53+
const maxAddItem = items.length + 10 > memoList.length ? memoList.length - items.length : 10;
54+
55+
if (maxAddItem === 0) return;
56+
57+
setItems([...items, ...getItems(nextGroupKey, maxAddItem)]);
58+
}}>
59+
{items.map(item => (
60+
<MemoItem data-grid-groupkey={item.groupKey} key={item.key} memo={memoList.at(item.key)} />
61+
))}
62+
</MasonryInfiniteGrid>
63+
);
64+
}
65+
66+
interface MemoItemProps {
67+
memo?: MemoRow;
68+
}
69+
70+
function MemoItem({ memo }: MemoItemProps) {
71+
if (!memo) return null;
72+
return (
73+
<div className="bg-base-100 shadow-xl card box-border w-[300px]">
74+
<div className="card-body">
75+
<Link className="font-bold line-clamp-2 link-hover" href={memo.url} target="_blank">
76+
{memo.title}
77+
</Link>
78+
<p className="whitespace-break-spaces">{memo.memo}</p>
79+
</div>
80+
</div>
81+
);
82+
}

packages/web/src/app/memos/components/MemoList.tsx packages/web/src/app/memos/components/MemoTable.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { useMemoDeleteMutation } from '@src/hooks';
77
import { getSupabaseClient } from '@src/utils/supabase.client';
88
import { UseQueryResult } from '@tanstack/react-query';
99

10-
export default function MemoList() {
10+
export default function MemoTable() {
1111
const { mutate: deleteMemoMutate } = useMemoDeleteMutation();
1212
const supabaseClient = getSupabaseClient();
1313
// TODO :타입 에러로 인해 타입 단언으로 임시 해결
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export { default as MemoList } from './MemoList';
1+
export { default as MemoTable } from './MemoTable';

packages/web/src/app/memos/page.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@ import { getMemoSupabase } from '@extension/shared/utils';
33
import { HydrationBoundaryWrapper } from '@src/components';
44
import { getSupabaseClient } from '@src/utils/supabase.server';
55
import { redirect } from 'next/navigation';
6-
import { MemoList } from './components';
6+
import MemoGrid from './components/MemoGrid';
77

88
export default async function Page() {
99
const supabaseClient = getSupabaseClient();
1010
const user = await supabaseClient.auth.getUser();
1111

1212
if (!user?.data?.user) redirect('/login');
1313
return (
14-
<main>
14+
<main className="flex justify-center">
1515
<HydrationBoundaryWrapper queryKey={queryKeys.memoList()} queryFn={() => getMemoSupabase(supabaseClient)}>
16-
<MemoList />
16+
<MemoGrid />
1717
</HydrationBoundaryWrapper>
1818
</main>
1919
);

pnpm-lock.yaml

+60
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)