From f9878736a2f0a695829a20ba4bcd33337c3a1880 Mon Sep 17 00:00:00 2001 From: MohamedBassem Date: Sat, 17 Feb 2024 12:54:43 +0000 Subject: feature: Inital attempt at showing a skeleton card while bookmark is loaded --- .../app/dashboard/bookmarks/components/AddLink.tsx | 8 ++++++ .../dashboard/bookmarks/components/Bookmarks.tsx | 1 - .../bookmarks/components/BookmarksGrid.tsx | 6 +++++ packages/web/lib/hooks/use-loading-card.ts | 9 +++++++ packages/web/package.json | 3 ++- yarn.lock | 30 ++++++++++++++++++++++ 6 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 packages/web/lib/hooks/use-loading-card.ts diff --git a/packages/web/app/dashboard/bookmarks/components/AddLink.tsx b/packages/web/app/dashboard/bookmarks/components/AddLink.tsx index 0ef4d193..6cd51c1d 100644 --- a/packages/web/app/dashboard/bookmarks/components/AddLink.tsx +++ b/packages/web/app/dashboard/bookmarks/components/AddLink.tsx @@ -10,6 +10,7 @@ import { zodResolver } from "@hookform/resolvers/zod"; import { toast } from "@/components/ui/use-toast"; import { api } from "@/lib/trpc"; import { ActionButton } from "@/components/ui/action-button"; +import { useLoadingCard } from "@/lib/hooks/use-loading-card"; const formSchema = z.object({ url: z.string().url({ message: "The link must be a valid URL" }), @@ -17,13 +18,20 @@ const formSchema = z.object({ export default function AddLink() { const router = useRouter(); + const {setLoading} = useLoadingCard(); const bookmarkLinkMutator = api.bookmarks.bookmarkLink.useMutation({ + onMutate: () => { + setLoading(true); + }, onSuccess: () => { router.refresh(); }, onError: () => { toast({ description: "Something went wrong", variant: "destructive" }); }, + onSettled: () => { + setLoading(false); + }, }); const form = useForm>({ diff --git a/packages/web/app/dashboard/bookmarks/components/Bookmarks.tsx b/packages/web/app/dashboard/bookmarks/components/Bookmarks.tsx index bd144a67..0afb42bd 100644 --- a/packages/web/app/dashboard/bookmarks/components/Bookmarks.tsx +++ b/packages/web/app/dashboard/bookmarks/components/Bookmarks.tsx @@ -14,7 +14,6 @@ export default async function Bookmarks({ redirect("/"); } - // TODO: Migrate to a server side call in trpc instead const bookmarks = await api.bookmarks.getBookmarks({ favourited, archived, diff --git a/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx b/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx index 711c296b..1963a980 100644 --- a/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx +++ b/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx @@ -1,3 +1,7 @@ +"use client"; + +import { useLoadingCard } from "@/lib/hooks/use-loading-card"; +import BookmarkCardSkeleton from "./BookmarkCardSkeleton"; import LinkCard from "./LinkCard"; import { ZBookmark } from "@/lib/types/api/bookmarks"; @@ -13,8 +17,10 @@ export default function BookmarksGrid({ }: { bookmarks: ZBookmark[]; }) { + const { loading } = useLoadingCard(); return (
+ {loading && } {bookmarks.map((b) => renderBookmark(b))}
); diff --git a/packages/web/lib/hooks/use-loading-card.ts b/packages/web/lib/hooks/use-loading-card.ts new file mode 100644 index 00000000..7bd7776a --- /dev/null +++ b/packages/web/lib/hooks/use-loading-card.ts @@ -0,0 +1,9 @@ +import { create } from "zustand"; + +export const useLoadingCard = create<{ + loading: boolean, + setLoading: (val: boolean) => void, +}>((set) => ({ + loading: false, + setLoading: (val: boolean) => set({ loading: val }), +})); diff --git a/packages/web/package.json b/packages/web/package.json index 997e4042..724845f5 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -40,7 +40,8 @@ "server-only": "^0.0.1", "tailwind-merge": "^2.2.1", "tailwindcss-animate": "^1.0.7", - "zod": "^3.22.4" + "zod": "^3.22.4", + "zustand": "^4.5.1" }, "devDependencies": { "@types/bcrypt": "^5.0.2", diff --git a/yarn.lock b/yarn.lock index 34c9c8f8..ff99251f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1676,6 +1676,7 @@ __metadata: tailwindcss: "npm:^3.3.0" tailwindcss-animate: "npm:^1.0.7" zod: "npm:^3.22.4" + zustand: "npm:^4.5.1" languageName: unknown linkType: soft @@ -9324,6 +9325,15 @@ __metadata: languageName: node linkType: hard +"use-sync-external-store@npm:1.2.0": + version: 1.2.0 + resolution: "use-sync-external-store@npm:1.2.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + checksum: 10c0/ac4814e5592524f242921157e791b022efe36e451fe0d4fd4d204322d5433a4fc300d63b0ade5185f8e0735ded044c70bcf6d2352db0f74d097a238cebd2da02 + languageName: node + linkType: hard + "util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -9743,3 +9753,23 @@ __metadata: checksum: 10c0/7578ab283dac0eee66a0ad0fc4a7f28c43e6745aadb3a529f59a4b851aa10872b3890398b3160f257f4b6817b4ce643debdda4fb21a2c040adda7862cab0a587 languageName: node linkType: hard + +"zustand@npm:^4.5.1": + version: 4.5.1 + resolution: "zustand@npm:4.5.1" + dependencies: + use-sync-external-store: "npm:1.2.0" + peerDependencies: + "@types/react": ">=16.8" + immer: ">=9.0.6" + react: ">=16.8" + peerDependenciesMeta: + "@types/react": + optional: true + immer: + optional: true + react: + optional: true + checksum: 10c0/3c928236f716f026760ddfff9910c37f9e3696169650cd677139dc2fe2623fa215dc31c899caf5b9b6a0668ed003c505918c2a953dbbd295fe7f90092634a90c + languageName: node + linkType: hard -- cgit v1.2.3-70-g09d2