Skip to content

Commit b5e731d

Browse files
committed
l;azy loaded module
1 parent dbb2331 commit b5e731d

7 files changed

Lines changed: 90 additions & 45 deletions

File tree

frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"test:github": "vitest --mode github",
4040
"test:ui": "vitest --ui",
4141
"coverage": "vitest --coverage",
42-
"visualize:app": "start dist/stats.html"
42+
"visualize": "start dist/stats.html"
4343
},
4444
"dependencies": {
4545
"@capacitor/android": "^8.0.1",
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
import { Loader2 } from "lucide-react"
3+
import { Button } from "./button"
4+
5+
function ButtonLoader({ className, ...props }: React.ComponentProps<"div">) {
6+
return (
7+
<Button
8+
variant="outline"
9+
disabled
10+
className="gap-2 opacity-70"
11+
>
12+
<Loader2 className="h-4 w-4 animate-spin" />
13+
</Button>
14+
)
15+
}
16+
17+
export { ButtonLoader }
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
import { Loader2 } from "lucide-react"
3+
4+
function Loader({ className, ...props }: React.ComponentProps<"div">) {
5+
return (
6+
<div className="flex items-center justify-center h-9 w-9">
7+
<Loader2 className="h-5 w-5 animate-spin text-muted-foreground" />
8+
</div>
9+
)
10+
}
11+
12+
export { Loader }

frontend/src/feature/quote/popover/filter.popover.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ interface TagFilterProps {
1515
onChange: (tags: string[]) => void
1616
}
1717

18-
export function TagFilter({ tags, value, onChange }: TagFilterProps) {
18+
export default function TagFilter({ tags, value, onChange }: TagFilterProps) {
1919
const [open, setOpen] = useState(false)
2020

2121
const toggleTag = (tag: string) => {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default function EditorSkeleton() {
2+
return (
3+
<div
4+
aria-label='loading-editor'
5+
className="border rounded-xl p-4 animate-pulse bg-muted">
6+
<div className="h-40 w-3/4 bg-gray-300 rounded mb-3" />
7+
</div>
8+
)
9+
}

frontend/src/page/quote/quote-list/quote-list.page.tsx

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
Lightbulb,
55
LightbulbOff,
66
SearchIcon,
7+
Loader2,
78
} from 'lucide-react'
89
import {
910
InputGroup,
@@ -16,16 +17,18 @@ import { Link } from '@tanstack/react-router'
1617
import { Button } from '@/components/ui/button'
1718
import { Suspense, lazy } from 'react'
1819
import { deleteQuoteWithLinks } from '@/db/quote_tags.db'
19-
import { TagFilter } from '@/feature/quote/popover/filter.popover'
2020
import type { Quote, QuoteDetails, QuoteFormData, Tag, SortOption } from '@/model/index.model'
2121
import { useGetAllQuoteDetails } from '@/api-hook/use-get-all-quote-details.hook'
2222
import { useSortStore } from '@/store/use-sort.store'
2323
import { toggleQuotePinned } from '@/db/quote.db'
2424
import React from 'react'
25+
import { ButtonLoader } from '@/components/ui/button-loader'
26+
import { Loader } from '@/components/ui/loader'
2527

2628
const DeleteQuoteDialog = lazy(() => import('@/feature/quote/dialog/delete.dialog'))
2729
const ListQuote = lazy(() => import('@/feature/quote/list.quote').then(mod => ({ default: mod.ListQuote })))
2830
const SettingComponent = lazy(() => import('@/feature/quote/dialog/setting.dialog').then(mod => ({ default: mod.default })))
31+
const TagFilterComponent = lazy(() => import('@/feature/quote/popover/filter.popover').then(mod => ({ default: mod.default })))
2932

3033
export function QuoteListPage() {
3134
const {
@@ -95,9 +98,9 @@ export function QuoteListPage() {
9598

9699
if (error) {
97100
return (
98-
<p
99-
aria-label='error'
100-
className="w-full text-center text-destructive">
101+
<p
102+
aria-label='error'
103+
className="w-full text-center text-destructive">
101104
Error: {error}
102105
</p>
103106
)
@@ -107,16 +110,18 @@ export function QuoteListPage() {
107110
<div className=" flex flex-col">
108111
{/* Sticky Header */}
109112
<div
110-
aria-label='sticky-header'
113+
aria-label='sticky-header'
111114
className="gap-2 p-2 flex flex-col sticky top-0 z-20 bg-background rounded-b"
112115
>
113116
<aside className="flex justify-between">
114-
<TagFilter
115-
tags={allTags}
116-
value={activeTags}
117-
onChange={setActiveTags}
118-
/>
119-
<Suspense fallback={null}>
117+
<Suspense fallback={<ButtonLoader />}>
118+
<TagFilterComponent
119+
tags={allTags}
120+
value={activeTags}
121+
onChange={setActiveTags}
122+
/>
123+
</Suspense>
124+
<Suspense fallback={<ButtonLoader />}>
120125
<SettingComponent />
121126
</Suspense>
122127
</aside>
@@ -129,24 +134,24 @@ export function QuoteListPage() {
129134
onChange={e => setSearch(e.target.value)}
130135
/>
131136
<InputGroupAddon>
132-
<SearchIcon aria-label='search-icon'/>
137+
<SearchIcon aria-label='search-icon' />
133138
</InputGroupAddon>
134139
</InputGroup>
135140

136141
</div>
137142

138143
{/* Content */}
139144
<main className="px-2">
140-
<Suspense fallback={<div aria-label='loading-list'>Loading list...</div>}>
141-
<div aria-label='list'>
142-
<ListQuote
143-
loading={isLoading}
144-
quotes={quotes}
145-
onEdit={() => { }}
146-
onDelete={openDeleteDialog}
147-
onTogglePin={handleTogglePin}
148-
/>
149-
</div>
145+
<Suspense fallback={<Loader aria-label='loading-list'/>}>
146+
<div aria-label='list'>
147+
<ListQuote
148+
loading={isLoading}
149+
quotes={quotes}
150+
onEdit={() => { }}
151+
onDelete={openDeleteDialog}
152+
onTogglePin={handleTogglePin}
153+
/>
154+
</div>
150155
</Suspense>
151156
</main>
152157

frontend/src/page/quote/quote/quote.page.tsx

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,25 @@ import { ArrowLeftIcon, Save, Shirt } from 'lucide-react'
1414
import { useGetSummarize } from '@/api-hook/ai-content-summarize.hook'
1515
import { useGetQuoteDetails } from '@/api-hook/use-get-quote-details.hook'
1616
import { createFileRoute, Link, useNavigate } from '@tanstack/react-router'
17-
import ChooseBackground from "@/feature/quote/drawer/choose-background.drawer"
1817
import type { Quote, QuoteDetails, QuoteFormData, Tag } from "@/model/index.model"
1918
import { addTagToQuote, deleteQuoteTagLinks, deleteQuoteWithLinks } from '@/db/quote_tags.db'
2019
import { useState, useEffect, useRef, useCallback, type Dispatch, type SetStateAction } from "react"
21-
import { ChatSheet } from "@/feature/quote/sheet/chat.sheet"
20+
import { ButtonLoader } from "@/components/ui/button-loader"
21+
import EditorSkeleton from "@/feature/quote/skeleton/editor.skeleton"
2222

2323
const Tiptap = lazy(() => import('@/components/common/tiptap-customized'))
2424
const ShareBackground = lazy(
2525
() => import('@/feature/quote/dialog/share.dialog')
2626
.then(mod => ({ default: mod.ShareBackground }))
2727
)
28+
const ChooseBackground = lazy(
29+
() => import('@/feature/quote/drawer/choose-background.drawer')
30+
.then(mod => ({ default: mod.default }))
31+
)
32+
const ChatSheet = lazy(
33+
() => import('@/feature/quote/sheet/chat.sheet')
34+
.then(mod => ({ default: mod.ChatSheet }))
35+
)
2836

2937

3038
interface Props {
@@ -35,7 +43,7 @@ export function QuotePage(props: Props) {
3543
const { mode } = props
3644
const navigate = useNavigate()
3745
const noteRef = useRef<HTMLDivElement>(null)
38-
const { getSummarize ,isPending:loadingSummarize, error: errorGetSummarize} = useGetSummarize()
46+
const { getSummarize, isPending: loadingSummarize, error: errorGetSummarize } = useGetSummarize()
3947

4048
// Only read params in edit mode
4149
const params = mode === 'edit' ? Route.useParams() : null
@@ -98,18 +106,6 @@ export function QuotePage(props: Props) {
98106
return result;
99107
};
100108

101-
const handleSummrise = async() => {
102-
let res = await getSummarize(quote?.text!)
103-
104-
let errorMessage = res?.error?.message
105-
if (errorMessage) {
106-
toast.error(errorMessage, { position: "top-center" })
107-
}
108-
console.log({res, errorGetSummarize, error,});
109-
110-
}
111-
112-
113109
const handleSubmit = useCallback(async (quote: QuoteFormData) => {
114110
let quoteId: number | undefined = quote.id
115111
if (quoteId) { // edit
@@ -203,15 +199,21 @@ export function QuotePage(props: Props) {
203199
</Button>
204200
</Link>
205201
<div className="flex gap-2" >
206-
<Suspense fallback={null}>
202+
<Suspense fallback={<ButtonLoader />}>
207203
<ShareBackground quoteFormData={quoteData} />
208204
</Suspense>
209-
<ChooseBackground onValueUpdate={onValueUpdate} />
210-
<ChatSheet text={quoteData?.text!} query="Summarize this note"/>
205+
206+
<Suspense fallback={<ButtonLoader />}>
207+
<ChooseBackground onValueUpdate={onValueUpdate} />
208+
</Suspense>
209+
210+
<Suspense fallback={<ButtonLoader />}>
211+
<ChatSheet text={quoteData?.text!} query="Summarize this note" />
212+
</Suspense>
211213
</div>
212214
</div>
213215

214-
{isLoading && <div aria-label="loading" >Loading...</div>}
216+
{isLoading && <div aria-label="loading" ><EditorSkeleton/></div>}
215217

216218
{error && <div aria-label="error" className="text-destructive">Error: {error}</div>}
217219

@@ -227,7 +229,7 @@ export function QuotePage(props: Props) {
227229
{/*
228230
<Label htmlFor="name-1">Quote</Label>
229231
*/}
230-
<Suspense fallback={<div aria-label='loading-editor'>Loading editor...</div>}>
232+
<Suspense fallback={<EditorSkeleton/>}>
231233
<div aria-label="editor" >
232234
<Tiptap
233235
key={quoteData?.id ?? "new"}
@@ -281,7 +283,7 @@ export function QuotePage(props: Props) {
281283
</div>
282284

283285

284-
{/* <Separator className=" bg-border" />
286+
{/* <Separator className=" bg-border" />
285287
286288
287289
<div className="flex">

0 commit comments

Comments
 (0)