aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMohamedBassem <me@mbassem.com>2024-03-13 22:37:41 +0000
committerMohamed Bassem <me@mbassem.com>2024-03-14 16:40:45 +0000
commita03f1dc2ac25579df30e8cb59d2703110c3e564d (patch)
tree59315e73cd83dc391660071c70752cf23989b3da
parent04572a8e5081b1e4871e273cde9dbaaa44c52fe0 (diff)
downloadkarakeep-a03f1dc2ac25579df30e8cb59d2703110c3e564d.tar.zst
lint: Lint and format the entire repo with the new configs
-rw-r--r--.husky/pre-commit2
-rw-r--r--apps/browser-extension/.eslintrc.cjs3
-rw-r--r--apps/browser-extension/src/BookmarkSavedPage.tsx1
-rw-r--r--apps/browser-extension/src/Layout.tsx1
-rw-r--r--apps/browser-extension/src/SignInPage.tsx1
-rw-r--r--apps/browser-extension/src/utils/settings.ts4
-rw-r--r--apps/browser-extension/tsconfig.json3
-rw-r--r--apps/mobile/.eslintrc.js4
-rw-r--r--apps/mobile/app.json4
-rw-r--r--apps/mobile/app/_layout.tsx5
-rw-r--r--apps/mobile/app/dashboard/(tabs)/_layout.tsx2
-rw-r--r--apps/mobile/app/dashboard/(tabs)/index.tsx5
-rw-r--r--apps/mobile/app/dashboard/(tabs)/lists.tsx3
-rw-r--r--apps/mobile/app/dashboard/(tabs)/search.tsx5
-rw-r--r--apps/mobile/app/dashboard/(tabs)/settings.tsx3
-rw-r--r--apps/mobile/app/dashboard/add-link.tsx11
-rw-r--r--apps/mobile/app/dashboard/add-note.tsx11
-rw-r--r--apps/mobile/app/dashboard/archive.tsx1
-rw-r--r--apps/mobile/app/dashboard/favourites.tsx1
-rw-r--r--apps/mobile/app/dashboard/lists/[slug].tsx3
-rw-r--r--apps/mobile/app/error.tsx2
-rw-r--r--apps/mobile/app/index.tsx3
-rw-r--r--apps/mobile/app/sharing.tsx12
-rw-r--r--apps/mobile/app/signin.tsx5
-rw-r--r--apps/mobile/components/Logo.tsx2
-rw-r--r--apps/mobile/components/bookmarks/BookmarkCard.tsx15
-rw-r--r--apps/mobile/components/bookmarks/BookmarkList.tsx5
-rw-r--r--apps/mobile/components/ui/ActionButton.tsx3
-rw-r--r--apps/mobile/components/ui/Button.tsx4
-rw-r--r--apps/mobile/components/ui/Divider.tsx1
-rw-r--r--apps/mobile/components/ui/FullPageSpinner.tsx2
-rw-r--r--apps/mobile/components/ui/Input.tsx5
-rw-r--r--apps/mobile/components/ui/Skeleton.tsx6
-rw-r--r--apps/mobile/components/ui/Toast.tsx3
-rw-r--r--apps/mobile/lib/providers.tsx12
-rw-r--r--apps/mobile/lib/session.ts2
-rw-r--r--apps/mobile/lib/settings.ts9
-rw-r--r--apps/mobile/lib/storage-state.ts6
-rw-r--r--apps/mobile/lib/trpc.ts3
-rw-r--r--apps/mobile/lib/utils.ts3
-rw-r--r--apps/mobile/metro.config.js7
-rw-r--r--apps/mobile/tailwind.config.ts1
-rw-r--r--apps/web/app/api/trpc/[trpc]/route.ts9
-rw-r--r--apps/web/app/dashboard/admin/page.tsx2
-rw-r--r--apps/web/app/dashboard/bookmarks/layout.tsx2
-rw-r--r--apps/web/app/dashboard/layout.tsx2
-rw-r--r--apps/web/app/dashboard/lists/[listId]/page.tsx6
-rw-r--r--apps/web/app/dashboard/lists/page.tsx2
-rw-r--r--apps/web/app/dashboard/preview/[bookmarkId]/page.tsx2
-rw-r--r--apps/web/app/dashboard/search/page.tsx5
-rw-r--r--apps/web/app/dashboard/settings/page.tsx1
-rw-r--r--apps/web/app/dashboard/tags/[tagName]/page.tsx7
-rw-r--r--apps/web/app/dashboard/tags/page.tsx9
-rw-r--r--apps/web/app/layout.tsx6
-rw-r--r--apps/web/app/page.tsx2
-rw-r--r--apps/web/app/signin/page.tsx4
-rw-r--r--apps/web/components/dashboard/bookmarks/AddLinkButton.tsx17
-rw-r--r--apps/web/components/dashboard/bookmarks/AddToListModal.tsx23
-rw-r--r--apps/web/components/dashboard/bookmarks/BookmarkCardSkeleton.tsx2
-rw-r--r--apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx14
-rw-r--r--apps/web/components/dashboard/bookmarks/BookmarkPreview.tsx9
-rw-r--r--apps/web/components/dashboard/bookmarks/BookmarkedTextEditor.tsx11
-rw-r--r--apps/web/components/dashboard/bookmarks/Bookmarks.tsx6
-rw-r--r--apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx15
-rw-r--r--apps/web/components/dashboard/bookmarks/LinkCard.tsx14
-rw-r--r--apps/web/components/dashboard/bookmarks/TagList.tsx7
-rw-r--r--apps/web/components/dashboard/bookmarks/TagModal.tsx14
-rw-r--r--apps/web/components/dashboard/bookmarks/TextCard.tsx16
-rw-r--r--apps/web/components/dashboard/bookmarks/TopNav.tsx9
-rw-r--r--apps/web/components/dashboard/lists/AllListsView.tsx9
-rw-r--r--apps/web/components/dashboard/lists/DeleteListButton.tsx11
-rw-r--r--apps/web/components/dashboard/lists/ListView.tsx5
-rw-r--r--apps/web/components/dashboard/search/SearchInput.tsx2
-rw-r--r--apps/web/components/dashboard/settings/AddApiKey.tsx34
-rw-r--r--apps/web/components/dashboard/settings/ApiKeySettings.tsx3
-rw-r--r--apps/web/components/dashboard/settings/DeleteApiKey.tsx9
-rw-r--r--apps/web/components/dashboard/sidebar/AllLists.tsx10
-rw-r--r--apps/web/components/dashboard/sidebar/ModileSidebar.tsx9
-rw-r--r--apps/web/components/dashboard/sidebar/ModileSidebarItem.tsx2
-rw-r--r--apps/web/components/dashboard/sidebar/NewListModal.tsx28
-rw-r--r--apps/web/components/dashboard/sidebar/Sidebar.tsx16
-rw-r--r--apps/web/components/dashboard/sidebar/SidebarItem.tsx2
-rw-r--r--apps/web/components/signin/CredentialsForm.tsx20
-rw-r--r--apps/web/components/signin/SignInForm.tsx3
-rw-r--r--apps/web/components/signin/SignInProviderButton.tsx4
-rw-r--r--apps/web/components/ui/action-button.tsx3
-rw-r--r--apps/web/components/ui/back-button.tsx4
-rw-r--r--apps/web/components/ui/badge.tsx12
-rw-r--r--apps/web/components/ui/button.tsx10
-rw-r--r--apps/web/components/ui/card.tsx6
-rw-r--r--apps/web/components/ui/dialog.tsx11
-rw-r--r--apps/web/components/ui/dropdown-menu.tsx17
-rw-r--r--apps/web/components/ui/form.tsx31
-rw-r--r--apps/web/components/ui/imageCard.tsx1
-rw-r--r--apps/web/components/ui/input.tsx6
-rw-r--r--apps/web/components/ui/label.tsx6
-rw-r--r--apps/web/components/ui/popover.tsx5
-rw-r--r--apps/web/components/ui/scroll-area.tsx5
-rw-r--r--apps/web/components/ui/select.tsx11
-rw-r--r--apps/web/components/ui/separator.tsx5
-rw-r--r--apps/web/components/ui/skeleton.tsx2
-rw-r--r--apps/web/components/ui/table.tsx9
-rw-r--r--apps/web/components/ui/tabs.tsx9
-rw-r--r--apps/web/components/ui/textarea.tsx6
-rw-r--r--apps/web/components/ui/toast.tsx16
-rw-r--r--apps/web/components/ui/use-toast.ts5
-rw-r--r--apps/web/lib/bookmarkUtils.tsx2
-rw-r--r--apps/web/lib/hooks/bookmark-search.ts4
-rw-r--r--apps/web/lib/providers.tsx12
-rw-r--r--apps/web/lib/trpc.tsx4
-rw-r--r--apps/web/lib/utils.ts3
-rw-r--r--apps/web/next.config.mjs6
-rw-r--r--apps/web/server/api/client.ts5
-rw-r--r--apps/web/server/auth.ts17
-rw-r--r--apps/web/vitest.config.ts2
-rw-r--r--package.json1
-rw-r--r--packages/shared/index.ts2
-rw-r--r--packages/trpc/index.ts14
-rw-r--r--tooling/eslint/base.js2
-rw-r--r--tooling/eslint/package.json2
-rw-r--r--tooling/eslint/react.js3
-rw-r--r--turbo.json9
122 files changed, 424 insertions, 411 deletions
diff --git a/.husky/pre-commit b/.husky/pre-commit
index 208f9a12..d466e587 100644
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,2 +1,2 @@
-pnpm format:check
+pnpm format
pnpm lint
diff --git a/apps/browser-extension/.eslintrc.cjs b/apps/browser-extension/.eslintrc.cjs
deleted file mode 100644
index 450106a4..00000000
--- a/apps/browser-extension/.eslintrc.cjs
+++ /dev/null
@@ -1,3 +0,0 @@
-module.exports = {
- ignorePatterns: ["dist/"],
-};
diff --git a/apps/browser-extension/src/BookmarkSavedPage.tsx b/apps/browser-extension/src/BookmarkSavedPage.tsx
index f25a83ba..5ff2cd39 100644
--- a/apps/browser-extension/src/BookmarkSavedPage.tsx
+++ b/apps/browser-extension/src/BookmarkSavedPage.tsx
@@ -35,6 +35,7 @@ export default function BookmarkSavedPage() {
<Link
className="flex gap-2 rounded-md p-3 text-black hover:text-black"
target="_blank"
+ rel="noreferrer"
to={`${settings.address}/dashboard/preview/${bookmarkId}`}
>
<ArrowUpRightFromSquare className="my-auto" size="20" />
diff --git a/apps/browser-extension/src/Layout.tsx b/apps/browser-extension/src/Layout.tsx
index f8279a18..6ca05fdd 100644
--- a/apps/browser-extension/src/Layout.tsx
+++ b/apps/browser-extension/src/Layout.tsx
@@ -26,6 +26,7 @@ export default function Layout() {
<a
className="flex gap-2 text-black"
target="_blank"
+ rel="noreferrer"
href={`${settings.address}/dashboard/bookmarks`}
>
<Home />
diff --git a/apps/browser-extension/src/SignInPage.tsx b/apps/browser-extension/src/SignInPage.tsx
index 6db7c348..5c49965c 100644
--- a/apps/browser-extension/src/SignInPage.tsx
+++ b/apps/browser-extension/src/SignInPage.tsx
@@ -17,7 +17,6 @@ export default function SignInPage() {
setSettings((s) => ({ ...s, apiKey: resp.key }));
navigate("/options");
},
- onError: () => {},
});
const [formData, setFormData] = useState<{
diff --git a/apps/browser-extension/src/utils/settings.ts b/apps/browser-extension/src/utils/settings.ts
index 37f474c0..f20e9827 100644
--- a/apps/browser-extension/src/utils/settings.ts
+++ b/apps/browser-extension/src/utils/settings.ts
@@ -1,9 +1,9 @@
import { useChromeStorageSync } from "use-chrome-storage";
-export type Settings = {
+export interface Settings {
apiKey: string;
address: string;
-};
+}
export default function usePluginSettings() {
const [settings, setSettings, _1, _2, isInit] = useChromeStorageSync(
diff --git a/apps/browser-extension/tsconfig.json b/apps/browser-extension/tsconfig.json
index a7fc6fbf..3a88f0af 100644
--- a/apps/browser-extension/tsconfig.json
+++ b/apps/browser-extension/tsconfig.json
@@ -20,6 +20,7 @@
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
- "include": ["src"],
+ "include": ["src", "vite.config.ts"],
+ "exclude": ["node_modules"],
"references": [{ "path": "./tsconfig.node.json" }]
}
diff --git a/apps/mobile/.eslintrc.js b/apps/mobile/.eslintrc.js
deleted file mode 100644
index 53beac49..00000000
--- a/apps/mobile/.eslintrc.js
+++ /dev/null
@@ -1,4 +0,0 @@
-module.exports = {
- root: true,
- extends: ["universe/native"],
-};
diff --git a/apps/mobile/app.json b/apps/mobile/app.json
index e16baa37..20424263 100644
--- a/apps/mobile/app.json
+++ b/apps/mobile/app.json
@@ -12,9 +12,7 @@
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
- "assetBundlePatterns": [
- "**/*"
- ],
+ "assetBundlePatterns": ["**/*"],
"ios": {
"supportsTablet": true,
"bundleIdentifier": "app.hoarder.hoardermobile",
diff --git a/apps/mobile/app/_layout.tsx b/apps/mobile/app/_layout.tsx
index 6304ced5..b338af5e 100644
--- a/apps/mobile/app/_layout.tsx
+++ b/apps/mobile/app/_layout.tsx
@@ -1,13 +1,12 @@
import "@/globals.css";
import "expo-dev-client";
+import { useEffect } from "react";
+import { View } from "react-native";
import { useRouter } from "expo-router";
import { Stack } from "expo-router/stack";
import { useShareIntent } from "expo-share-intent";
import { StatusBar } from "expo-status-bar";
-import { useEffect } from "react";
-import { View } from "react-native";
-
import { useLastSharedIntent } from "@/lib/last-shared-intent";
import { Providers } from "@/lib/providers";
diff --git a/apps/mobile/app/dashboard/(tabs)/_layout.tsx b/apps/mobile/app/dashboard/(tabs)/_layout.tsx
index 5b2d810a..ce73a5c9 100644
--- a/apps/mobile/app/dashboard/(tabs)/_layout.tsx
+++ b/apps/mobile/app/dashboard/(tabs)/_layout.tsx
@@ -1,6 +1,6 @@
+import React from "react";
import { Tabs } from "expo-router";
import { ClipboardList, Home, Search, Settings } from "lucide-react-native";
-import React from "react";
export default function TabLayout() {
return (
diff --git a/apps/mobile/app/dashboard/(tabs)/index.tsx b/apps/mobile/app/dashboard/(tabs)/index.tsx
index b2349525..fe15956c 100644
--- a/apps/mobile/app/dashboard/(tabs)/index.tsx
+++ b/apps/mobile/app/dashboard/(tabs)/index.tsx
@@ -1,8 +1,7 @@
-import { Link, Stack } from "expo-router";
-import { SquarePen, Link as LinkIcon } from "lucide-react-native";
import { View } from "react-native";
-
+import { Link, Stack } from "expo-router";
import BookmarkList from "@/components/bookmarks/BookmarkList";
+import { Link as LinkIcon, SquarePen } from "lucide-react-native";
function HeaderRight() {
return (
diff --git a/apps/mobile/app/dashboard/(tabs)/lists.tsx b/apps/mobile/app/dashboard/(tabs)/lists.tsx
index b534ddda..a293757b 100644
--- a/apps/mobile/app/dashboard/(tabs)/lists.tsx
+++ b/apps/mobile/app/dashboard/(tabs)/lists.tsx
@@ -1,7 +1,6 @@
-import { Link } from "expo-router";
import { useEffect, useState } from "react";
import { FlatList, View } from "react-native";
-
+import { Link } from "expo-router";
import { api } from "@/lib/trpc";
export default function Lists() {
diff --git a/apps/mobile/app/dashboard/(tabs)/search.tsx b/apps/mobile/app/dashboard/(tabs)/search.tsx
index 980cab36..0025262e 100644
--- a/apps/mobile/app/dashboard/(tabs)/search.tsx
+++ b/apps/mobile/app/dashboard/(tabs)/search.tsx
@@ -1,12 +1,11 @@
-import { keepPreviousData } from "@tanstack/react-query";
import { useState } from "react";
import { View } from "react-native";
-import { useDebounce } from "use-debounce";
-
import BookmarkList from "@/components/bookmarks/BookmarkList";
import { Divider } from "@/components/ui/Divider";
import { Input } from "@/components/ui/Input";
import { api } from "@/lib/trpc";
+import { keepPreviousData } from "@tanstack/react-query";
+import { useDebounce } from "use-debounce";
export default function Search() {
const [search, setSearch] = useState("");
diff --git a/apps/mobile/app/dashboard/(tabs)/settings.tsx b/apps/mobile/app/dashboard/(tabs)/settings.tsx
index 9f86d5ec..81b21fc8 100644
--- a/apps/mobile/app/dashboard/(tabs)/settings.tsx
+++ b/apps/mobile/app/dashboard/(tabs)/settings.tsx
@@ -1,7 +1,6 @@
-import { useRouter } from "expo-router";
import { useEffect } from "react";
import { Text, View } from "react-native";
-
+import { useRouter } from "expo-router";
import Logo from "@/components/Logo";
import { Button } from "@/components/ui/Button";
import { useSession } from "@/lib/session";
diff --git a/apps/mobile/app/dashboard/add-link.tsx b/apps/mobile/app/dashboard/add-link.tsx
index 69a9c7a2..568a36b6 100644
--- a/apps/mobile/app/dashboard/add-link.tsx
+++ b/apps/mobile/app/dashboard/add-link.tsx
@@ -1,7 +1,6 @@
-import { useRouter } from "expo-router";
import { useState } from "react";
-import { View, Text } from "react-native";
-
+import { Text, View } from "react-native";
+import { useRouter } from "expo-router";
import { Button } from "@/components/ui/Button";
import { Input } from "@/components/ui/Input";
import { api } from "@/lib/trpc";
@@ -24,9 +23,9 @@ export default function AddNote() {
},
onError: (e) => {
let message;
- if (e.data?.code === "BAD_REQUEST") {
- const error = JSON.parse(e.message)[0];
- message = error.message;
+ if (e.data?.zodError) {
+ const zodError = e.data.zodError;
+ message = JSON.stringify(zodError);
} else {
message = `Something went wrong: ${e.message}`;
}
diff --git a/apps/mobile/app/dashboard/add-note.tsx b/apps/mobile/app/dashboard/add-note.tsx
index cf775a15..1f903e94 100644
--- a/apps/mobile/app/dashboard/add-note.tsx
+++ b/apps/mobile/app/dashboard/add-note.tsx
@@ -1,7 +1,6 @@
-import { useRouter } from "expo-router";
import { useState } from "react";
-import { View, Text } from "react-native";
-
+import { Text, View } from "react-native";
+import { useRouter } from "expo-router";
import { Button } from "@/components/ui/Button";
import { Input } from "@/components/ui/Input";
import { api } from "@/lib/trpc";
@@ -24,9 +23,9 @@ export default function AddNote() {
},
onError: (e) => {
let message;
- if (e.data?.code === "BAD_REQUEST") {
- const error = JSON.parse(e.message)[0];
- message = error.message;
+ if (e.data?.zodError) {
+ const zodError = e.data.zodError;
+ message = JSON.stringify(zodError);
} else {
message = `Something went wrong: ${e.message}`;
}
diff --git a/apps/mobile/app/dashboard/archive.tsx b/apps/mobile/app/dashboard/archive.tsx
index d75cfe22..2c559684 100644
--- a/apps/mobile/app/dashboard/archive.tsx
+++ b/apps/mobile/app/dashboard/archive.tsx
@@ -1,5 +1,4 @@
import { View } from "react-native";
-
import BookmarkList from "@/components/bookmarks/BookmarkList";
export default function Archive() {
diff --git a/apps/mobile/app/dashboard/favourites.tsx b/apps/mobile/app/dashboard/favourites.tsx
index 90374f18..42a139f9 100644
--- a/apps/mobile/app/dashboard/favourites.tsx
+++ b/apps/mobile/app/dashboard/favourites.tsx
@@ -1,5 +1,4 @@
import { View } from "react-native";
-
import BookmarkList from "@/components/bookmarks/BookmarkList";
export default function Favourites() {
diff --git a/apps/mobile/app/dashboard/lists/[slug].tsx b/apps/mobile/app/dashboard/lists/[slug].tsx
index 54744874..fdd67763 100644
--- a/apps/mobile/app/dashboard/lists/[slug].tsx
+++ b/apps/mobile/app/dashboard/lists/[slug].tsx
@@ -1,6 +1,5 @@
-import { useLocalSearchParams, Stack } from "expo-router";
import { View } from "react-native";
-
+import { Stack, useLocalSearchParams } from "expo-router";
import BookmarkList from "@/components/bookmarks/BookmarkList";
import FullPageSpinner from "@/components/ui/FullPageSpinner";
import { api } from "@/lib/trpc";
diff --git a/apps/mobile/app/error.tsx b/apps/mobile/app/error.tsx
index 2ca227a4..d0e4a7df 100644
--- a/apps/mobile/app/error.tsx
+++ b/apps/mobile/app/error.tsx
@@ -1,4 +1,4 @@
-import { View, Text } from "react-native";
+import { Text, View } from "react-native";
export default function ErrorPage() {
return (
diff --git a/apps/mobile/app/index.tsx b/apps/mobile/app/index.tsx
index 5ce20cda..f075fd6d 100644
--- a/apps/mobile/app/index.tsx
+++ b/apps/mobile/app/index.tsx
@@ -1,7 +1,6 @@
-import { useRouter } from "expo-router";
import { useEffect } from "react";
import { View } from "react-native";
-
+import { useRouter } from "expo-router";
import { useSession } from "@/lib/session";
export default function App() {
diff --git a/apps/mobile/app/sharing.tsx b/apps/mobile/app/sharing.tsx
index 64bbd933..f9f423b5 100644
--- a/apps/mobile/app/sharing.tsx
+++ b/apps/mobile/app/sharing.tsx
@@ -1,10 +1,10 @@
-import { Link, useLocalSearchParams, useRouter } from "expo-router";
-import { ShareIntent, useShareIntent } from "expo-share-intent";
+import type { ShareIntent } from "expo-share-intent";
import { useEffect, useMemo, useState } from "react";
-import { View, Text } from "react-native";
-import { z } from "zod";
-
+import { Text, View } from "react-native";
+import { Link, useLocalSearchParams, useRouter } from "expo-router";
+import { useShareIntent } from "expo-share-intent";
import { api } from "@/lib/trpc";
+import { z } from "zod";
type Mode =
| { type: "idle" }
@@ -18,7 +18,7 @@ function SaveBookmark({ setMode }: { setMode: (mode: Mode) => void }) {
const params = useLocalSearchParams();
const shareIntent = useMemo(() => {
- if (params && params.shareIntent) {
+ if (params?.shareIntent) {
if (typeof params.shareIntent === "string") {
return JSON.parse(params.shareIntent) as ShareIntent;
}
diff --git a/apps/mobile/app/signin.tsx b/apps/mobile/app/signin.tsx
index a89b0087..63e48f22 100644
--- a/apps/mobile/app/signin.tsx
+++ b/apps/mobile/app/signin.tsx
@@ -1,7 +1,6 @@
-import { useRouter } from "expo-router";
import { useEffect, useState } from "react";
-import { View, Text } from "react-native";
-
+import { Text, View } from "react-native";
+import { useRouter } from "expo-router";
import Logo from "@/components/Logo";
import { Button } from "@/components/ui/Button";
import { Input } from "@/components/ui/Input";
diff --git a/apps/mobile/components/Logo.tsx b/apps/mobile/components/Logo.tsx
index 57f7a5c3..f5f823b5 100644
--- a/apps/mobile/components/Logo.tsx
+++ b/apps/mobile/components/Logo.tsx
@@ -1,5 +1,5 @@
+import { Text, View } from "react-native";
import { PackageOpen } from "lucide-react-native";
-import { View, Text } from "react-native";
export default function Logo() {
return (
diff --git a/apps/mobile/components/bookmarks/BookmarkCard.tsx b/apps/mobile/components/bookmarks/BookmarkCard.tsx
index 25947790..93a059f8 100644
--- a/apps/mobile/components/bookmarks/BookmarkCard.tsx
+++ b/apps/mobile/components/bookmarks/BookmarkCard.tsx
@@ -1,16 +1,16 @@
-import { ZBookmark } from "@hoarder/trpc/types/bookmarks";
-import * as WebBrowser from "expo-web-browser";
-import { Star, Archive, Trash, ArchiveRestore } from "lucide-react-native";
-import { View, Text, Image, ScrollView, Pressable } from "react-native";
+import { Image, Pressable, ScrollView, Text, View } from "react-native";
import Markdown from "react-native-markdown-display";
+import * as WebBrowser from "expo-web-browser";
+import { api } from "@/lib/trpc";
+import { Archive, ArchiveRestore, Star, Trash } from "lucide-react-native";
+
+import type { ZBookmark } from "@hoarder/trpc/types/bookmarks";
import { ActionButton } from "../ui/ActionButton";
import { Divider } from "../ui/Divider";
import { Skeleton } from "../ui/Skeleton";
import { useToast } from "../ui/Toast";
-import { api } from "@/lib/trpc";
-
const MAX_LOADING_MSEC = 30 * 1000;
export function isBookmarkStillCrawling(bookmark: ZBookmark) {
@@ -155,6 +155,7 @@ function LinkCard({ bookmark }: { bookmark: ZBookmark }) {
/>
) : (
<Image
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
source={require("@/assets/blur.jpeg")}
className="h-56 w-full rounded-t-lg"
/>
@@ -168,7 +169,7 @@ function LinkCard({ bookmark }: { bookmark: ZBookmark }) {
className="line-clamp-2 text-xl font-bold"
onPress={() => WebBrowser.openBrowserAsync(url)}
>
- {bookmark.content.title || parsedUrl.host}
+ {bookmark.content.title ?? parsedUrl.host}
</Text>
<TagList bookmark={bookmark} />
<Divider orientation="vertical" className="mt-2 h-0.5 w-full" />
diff --git a/apps/mobile/components/bookmarks/BookmarkList.tsx b/apps/mobile/components/bookmarks/BookmarkList.tsx
index 8e408709..79d3d79e 100644
--- a/apps/mobile/components/bookmarks/BookmarkList.tsx
+++ b/apps/mobile/components/bookmarks/BookmarkList.tsx
@@ -1,11 +1,10 @@
import { useEffect, useState } from "react";
import { Text, View } from "react-native";
import Animated, { LinearTransition } from "react-native-reanimated";
+import { api } from "@/lib/trpc";
-import BookmarkCard from "./BookmarkCard";
import FullPageSpinner from "../ui/FullPageSpinner";
-
-import { api } from "@/lib/trpc";
+import BookmarkCard from "./BookmarkCard";
export default function BookmarkList({
favourited,
diff --git a/apps/mobile/components/ui/ActionButton.tsx b/apps/mobile/components/ui/ActionButton.tsx
index c51eb332..1f2e05ca 100644
--- a/apps/mobile/components/ui/ActionButton.tsx
+++ b/apps/mobile/components/ui/ActionButton.tsx
@@ -1,4 +1,5 @@
-import { ActivityIndicator, Pressable, PressableProps } from "react-native";
+import type { PressableProps } from "react-native";
+import { ActivityIndicator, Pressable } from "react-native";
export function ActionButton({
children,
diff --git a/apps/mobile/components/ui/Button.tsx b/apps/mobile/components/ui/Button.tsx
index 4c3cbc69..0f3b4ab3 100644
--- a/apps/mobile/components/ui/Button.tsx
+++ b/apps/mobile/components/ui/Button.tsx
@@ -1,7 +1,7 @@
-import { type VariantProps, cva } from "class-variance-authority";
+import type { VariantProps } from "class-variance-authority";
import { Text, TouchableOpacity } from "react-native";
-
import { cn } from "@/lib/utils";
+import { cva } from "class-variance-authority";
const buttonVariants = cva(
"flex flex-row items-center justify-center rounded-md",
diff --git a/apps/mobile/components/ui/Divider.tsx b/apps/mobile/components/ui/Divider.tsx
index 1da0a71e..cf1b4624 100644
--- a/apps/mobile/components/ui/Divider.tsx
+++ b/apps/mobile/components/ui/Divider.tsx
@@ -1,5 +1,4 @@
import { View } from "react-native";
-
import { cn } from "@/lib/utils";
function Divider({
diff --git a/apps/mobile/components/ui/FullPageSpinner.tsx b/apps/mobile/components/ui/FullPageSpinner.tsx
index 01187f11..89b66090 100644
--- a/apps/mobile/components/ui/FullPageSpinner.tsx
+++ b/apps/mobile/components/ui/FullPageSpinner.tsx
@@ -1,4 +1,4 @@
-import { View, ActivityIndicator } from "react-native";
+import { ActivityIndicator, View } from "react-native";
export default function FullPageSpinner() {
return (
diff --git a/apps/mobile/components/ui/Input.tsx b/apps/mobile/components/ui/Input.tsx
index 2fcb2764..01c9fb2f 100644
--- a/apps/mobile/components/ui/Input.tsx
+++ b/apps/mobile/components/ui/Input.tsx
@@ -1,6 +1,5 @@
import { forwardRef } from "react";
import { Text, TextInput, View } from "react-native";
-
import { cn } from "@/lib/utils";
export interface InputProps
@@ -15,14 +14,16 @@ const Input = forwardRef<React.ElementRef<typeof TextInput>, InputProps>(
<View className={cn("flex flex-col gap-1.5", className)}>
{label && <Text className={cn("text-base", labelClasses)}>{label}</Text>}
<TextInput
+ ref={ref}
className={cn(
inputClasses,
- "border-input rounded-lg border px-4 py-2.5",
+ "rounded-lg border border-input px-4 py-2.5",
)}
{...props}
/>
</View>
),
);
+Input.displayName = "Input";
export { Input };
diff --git a/apps/mobile/components/ui/Skeleton.tsx b/apps/mobile/components/ui/Skeleton.tsx
index 68b22e1e..3287b9ef 100644
--- a/apps/mobile/components/ui/Skeleton.tsx
+++ b/apps/mobile/components/ui/Skeleton.tsx
@@ -1,6 +1,6 @@
+import type { View } from "react-native";
import { useEffect, useRef } from "react";
-import { Animated, type View } from "react-native";
-
+import { Animated } from "react-native";
import { cn } from "@/lib/utils";
function Skeleton({
@@ -28,7 +28,7 @@ function Skeleton({
return (
<Animated.View
- className={cn("bg-muted rounded-md", className)}
+ className={cn("rounded-md bg-muted", className)}
style={[{ opacity: fadeAnim }]}
{...props}
/>
diff --git a/apps/mobile/components/ui/Toast.tsx b/apps/mobile/components/ui/Toast.tsx
index fb319f84..9aa25e5c 100644
--- a/apps/mobile/components/ui/Toast.tsx
+++ b/apps/mobile/components/ui/Toast.tsx
@@ -1,6 +1,5 @@
import { createContext, useContext, useEffect, useRef, useState } from "react";
import { Animated, Text, View } from "react-native";
-
import { cn } from "@/lib/utils";
const toastVariants = {
@@ -67,7 +66,7 @@ function Toast({
],
}}
>
- <Text className="text-background text-left font-semibold">{message}</Text>
+ <Text className="text-left font-semibold text-background">{message}</Text>
{showProgress && (
<View className="mt-2 rounded">
<Animated.View
diff --git a/apps/mobile/lib/providers.tsx b/apps/mobile/lib/providers.tsx
index 1717afb2..036e8ae2 100644
--- a/apps/mobile/lib/providers.tsx
+++ b/apps/mobile/lib/providers.tsx
@@ -1,13 +1,12 @@
+import { useEffect, useState } from "react";
+import { ToastProvider } from "@/components/ui/Toast";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { httpBatchLink } from "@trpc/client";
-import { useEffect, useState } from "react";
import superjson from "superjson";
import useAppSettings, { getAppSettings } from "./settings";
import { api } from "./trpc";
-import { ToastProvider } from "@/components/ui/Toast";
-
function getTRPCClient(address: string) {
return api.createClient({
links: [
@@ -16,10 +15,9 @@ function getTRPCClient(address: string) {
async headers() {
const settings = await getAppSettings();
return {
- Authorization:
- settings && settings.apiKey
- ? `Bearer ${settings.apiKey}`
- : undefined,
+ Authorization: settings?.apiKey
+ ? `Bearer ${settings.apiKey}`
+ : undefined,
};
},
transformer: superjson,
diff --git a/apps/mobile/lib/session.ts b/apps/mobile/lib/session.ts
index e2ab245b..071748b9 100644
--- a/apps/mobile/lib/session.ts
+++ b/apps/mobile/lib/session.ts
@@ -10,7 +10,7 @@ export function useSession() {
const logout = useCallback(() => {
setSettings({ ...settings, apiKey: undefined });
- }, [settings]);
+ }, [settings, setSettings]);
return {
isLoggedIn,
diff --git a/apps/mobile/lib/settings.ts b/apps/mobile/lib/settings.ts
index 21f40528..13de067e 100644
--- a/apps/mobile/lib/settings.ts
+++ b/apps/mobile/lib/settings.ts
@@ -4,14 +4,15 @@ import { useStorageState } from "./storage-state";
const SETTING_NAME = "settings";
-export type Settings = {
+export interface Settings {
apiKey?: string;
address: string;
-};
+}
export default function useAppSettings() {
- let [[isLoading, settings], setSettings] =
- useStorageState<Settings>(SETTING_NAME);
+ const [settingsState, setSettings] = useStorageState<Settings>(SETTING_NAME);
+ const [isLoading] = settingsState;
+ let [, settings] = settingsState;
settings ||= {
address: "https://demo.hoarder.app",
diff --git a/apps/mobile/lib/storage-state.ts b/apps/mobile/lib/storage-state.ts
index 4988f0e0..f45ddfe5 100644
--- a/apps/mobile/lib/storage-state.ts
+++ b/apps/mobile/lib/storage-state.ts
@@ -1,5 +1,5 @@
-import * as SecureStore from "expo-secure-store";
import * as React from "react";
+import * as SecureStore from "expo-secure-store";
type UseStateHook<T> = [[boolean, T | null], (value: T | null) => void];
@@ -8,7 +8,7 @@ function useAsyncState<T>(
): UseStateHook<T> {
return React.useReducer(
(
- state: [boolean, T | null],
+ _state: [boolean, T | null],
action: T | null = null,
): [boolean, T | null] => [false, action],
initialValue,
@@ -34,7 +34,7 @@ export function useStorageState<T>(key: string): UseStateHook<T> {
setState(null);
return null;
}
- setState(JSON.parse(value));
+ setState(JSON.parse(value) as T);
});
}, [key]);
diff --git a/apps/mobile/lib/trpc.ts b/apps/mobile/lib/trpc.ts
index 6b428bd9..9b025df1 100644
--- a/apps/mobile/lib/trpc.ts
+++ b/apps/mobile/lib/trpc.ts
@@ -1,4 +1,5 @@
-import type { AppRouter } from "@hoarder/trpc/routers/_app";
import { createTRPCReact } from "@trpc/react-query";
+import type { AppRouter } from "@hoarder/trpc/routers/_app";
+
export const api = createTRPCReact<AppRouter>();
diff --git a/apps/mobile/lib/utils.ts b/apps/mobile/lib/utils.ts
index 365058ce..88283f01 100644
--- a/apps/mobile/lib/utils.ts
+++ b/apps/mobile/lib/utils.ts
@@ -1,4 +1,5 @@
-import { type ClassValue, clsx } from "clsx";
+import type { ClassValue } from "clsx";
+import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
diff --git a/apps/mobile/metro.config.js b/apps/mobile/metro.config.js
index c5630a83..f9679cb2 100644
--- a/apps/mobile/metro.config.js
+++ b/apps/mobile/metro.config.js
@@ -2,11 +2,11 @@
const { getDefaultConfig } = require("expo/metro-config");
const { FileStore } = require("metro-cache");
const { withNativeWind } = require("nativewind/metro");
-
const path = require("path");
module.exports = withTurborepoManagedCache(
withMonorepoPaths(
+ // eslint-disable-next-line no-undef
withNativeWind(getDefaultConfig(__dirname), {
input: "./globals.css",
configPath: "./tailwind.config.ts",
@@ -23,6 +23,7 @@ module.exports = withTurborepoManagedCache(
* @returns {import('expo/metro-config').MetroConfig}
*/
function withMonorepoPaths(config) {
+ // eslint-disable-next-line no-undef
const projectRoot = __dirname;
const workspaceRoot = path.resolve(projectRoot, "../..");
@@ -49,10 +50,8 @@ function withMonorepoPaths(config) {
*/
function withTurborepoManagedCache(config) {
config.cacheStores = [
+ // eslint-disable-next-line no-undef
new FileStore({ root: path.join(__dirname, "node_modules/.cache/metro") }),
];
return config;
}
-
-
-
diff --git a/apps/mobile/tailwind.config.ts b/apps/mobile/tailwind.config.ts
index ce0059d4..fef31daf 100644
--- a/apps/mobile/tailwind.config.ts
+++ b/apps/mobile/tailwind.config.ts
@@ -50,6 +50,7 @@ const config = {
},
},
borderWidth: {
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment
hairline: hairlineWidth(),
},
keyframes: {
diff --git a/apps/web/app/api/trpc/[trpc]/route.ts b/apps/web/app/api/trpc/[trpc]/route.ts
index 02ca966d..23df286f 100644
--- a/apps/web/app/api/trpc/[trpc]/route.ts
+++ b/apps/web/app/api/trpc/[trpc]/route.ts
@@ -1,8 +1,9 @@
-import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
-import { appRouter } from "@hoarder/trpc/routers/_app";
import { createContext } from "@/server/api/client";
-import { authenticateApiKey } from "@hoarder/trpc/auth";
+import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
+
import { db } from "@hoarder/db";
+import { authenticateApiKey } from "@hoarder/trpc/auth";
+import { appRouter } from "@hoarder/trpc/routers/_app";
const handler = (req: Request) =>
fetchRequestHandler({
@@ -21,7 +22,7 @@ const handler = (req: Request) =>
// Check if the request has an Authorization token, if it does, assume that API key authentication is requested.
const authorizationHeader = opts.req.headers.get("Authorization");
if (authorizationHeader && authorizationHeader.startsWith("Bearer ")) {
- const token = authorizationHeader.split(" ")[1]!;
+ const token = authorizationHeader.split(" ")[1];
try {
const user = await authenticateApiKey(token);
return { user, db };
diff --git a/apps/web/app/dashboard/admin/page.tsx b/apps/web/app/dashboard/admin/page.tsx
index 6babdd79..7b4c3cdd 100644
--- a/apps/web/app/dashboard/admin/page.tsx
+++ b/apps/web/app/dashboard/admin/page.tsx
@@ -1,5 +1,6 @@
"use client";
+import { useRouter } from "next/navigation";
import { ActionButton } from "@/components/ui/action-button";
import LoadingSpinner from "@/components/ui/spinner";
import {
@@ -15,7 +16,6 @@ import { api } from "@/lib/trpc";
import { keepPreviousData } from "@tanstack/react-query";
import { Trash } from "lucide-react";
import { useSession } from "next-auth/react";
-import { useRouter } from "next/navigation";
function ActionsSection() {
const { mutate: recrawlLinks, isPending: isRecrawlPending } =
diff --git a/apps/web/app/dashboard/bookmarks/layout.tsx b/apps/web/app/dashboard/bookmarks/layout.tsx
index 71ee143b..ca99a87b 100644
--- a/apps/web/app/dashboard/bookmarks/layout.tsx
+++ b/apps/web/app/dashboard/bookmarks/layout.tsx
@@ -1,6 +1,6 @@
+import type { Metadata } from "next";
import React from "react";
import TopNav from "@/components/dashboard/bookmarks/TopNav";
-import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Hoarder - Bookmarks",
diff --git a/apps/web/app/dashboard/layout.tsx b/apps/web/app/dashboard/layout.tsx
index 31d592fb..dc3af9c7 100644
--- a/apps/web/app/dashboard/layout.tsx
+++ b/apps/web/app/dashboard/layout.tsx
@@ -1,6 +1,6 @@
-import { Separator } from "@/components/ui/separator";
import MobileSidebar from "@/components/dashboard/sidebar/ModileSidebar";
import Sidebar from "@/components/dashboard/sidebar/Sidebar";
+import { Separator } from "@/components/ui/separator";
export default async function Dashboard({
children,
diff --git a/apps/web/app/dashboard/lists/[listId]/page.tsx b/apps/web/app/dashboard/lists/[listId]/page.tsx
index 006fd3ad..4e35c377 100644
--- a/apps/web/app/dashboard/lists/[listId]/page.tsx
+++ b/apps/web/app/dashboard/lists/[listId]/page.tsx
@@ -1,9 +1,9 @@
+import { notFound, redirect } from "next/navigation";
+import DeleteListButton from "@/components/dashboard/lists/DeleteListButton";
+import ListView from "@/components/dashboard/lists/ListView";
import { api } from "@/server/api/client";
import { getServerAuthSession } from "@/server/auth";
import { TRPCError } from "@trpc/server";
-import { notFound, redirect } from "next/navigation";
-import ListView from "@/components/dashboard/lists/ListView";
-import DeleteListButton from "@/components/dashboard/lists/DeleteListButton";
export default async function ListPage({
params,
diff --git a/apps/web/app/dashboard/lists/page.tsx b/apps/web/app/dashboard/lists/page.tsx
index 88eeda47..a8c53eb6 100644
--- a/apps/web/app/dashboard/lists/page.tsx
+++ b/apps/web/app/dashboard/lists/page.tsx
@@ -1,5 +1,5 @@
-import { api } from "@/server/api/client";
import AllListsView from "@/components/dashboard/lists/AllListsView";
+import { api } from "@/server/api/client";
export default async function ListsPage() {
const lists = await api.lists.list();
diff --git a/apps/web/app/dashboard/preview/[bookmarkId]/page.tsx b/apps/web/app/dashboard/preview/[bookmarkId]/page.tsx
index 707d2b69..5f10b56e 100644
--- a/apps/web/app/dashboard/preview/[bookmarkId]/page.tsx
+++ b/apps/web/app/dashboard/preview/[bookmarkId]/page.tsx
@@ -1,5 +1,5 @@
-import { api } from "@/server/api/client";
import BookmarkPreview from "@/components/dashboard/bookmarks/BookmarkPreview";
+import { api } from "@/server/api/client";
export default async function BookmarkPreviewPage({
params,
diff --git a/apps/web/app/dashboard/search/page.tsx b/apps/web/app/dashboard/search/page.tsx
index 602f6aa0..38099c18 100644
--- a/apps/web/app/dashboard/search/page.tsx
+++ b/apps/web/app/dashboard/search/page.tsx
@@ -1,11 +1,12 @@
"use client";
-import BookmarksGrid from "@/components/dashboard/bookmarks/BookmarksGrid";
-import Loading from "../bookmarks/loading";
import { Suspense, useRef } from "react";
+import BookmarksGrid from "@/components/dashboard/bookmarks/BookmarksGrid";
import { SearchInput } from "@/components/dashboard/search/SearchInput";
import { useBookmarkSearch } from "@/lib/hooks/bookmark-search";
+import Loading from "../bookmarks/loading";
+
function SearchComp() {
const { data, isPending, isPlaceholderData } = useBookmarkSearch();
diff --git a/apps/web/app/dashboard/settings/page.tsx b/apps/web/app/dashboard/settings/page.tsx
index 38091e6c..3d54d2d7 100644
--- a/apps/web/app/dashboard/settings/page.tsx
+++ b/apps/web/app/dashboard/settings/page.tsx
@@ -1,4 +1,5 @@
import ApiKeySettings from "@/components/dashboard/settings/ApiKeySettings";
+
export default async function Settings() {
return (
<div className="m-4 flex flex-col space-y-2 rounded-md border bg-white p-4">
diff --git a/apps/web/app/dashboard/tags/[tagName]/page.tsx b/apps/web/app/dashboard/tags/[tagName]/page.tsx
index c978b86a..51b3cb0b 100644
--- a/apps/web/app/dashboard/tags/[tagName]/page.tsx
+++ b/apps/web/app/dashboard/tags/[tagName]/page.tsx
@@ -1,11 +1,12 @@
-import { getServerAuthSession } from "@/server/auth";
-import { db } from "@hoarder/db";
import { notFound, redirect } from "next/navigation";
import BookmarksGrid from "@/components/dashboard/bookmarks/BookmarksGrid";
import { api } from "@/server/api/client";
-import { bookmarkTags, tagsOnBookmarks } from "@hoarder/db/schema";
+import { getServerAuthSession } from "@/server/auth";
import { and, eq } from "drizzle-orm";
+import { db } from "@hoarder/db";
+import { bookmarkTags, tagsOnBookmarks } from "@hoarder/db/schema";
+
export default async function TagPage({
params,
}: {
diff --git a/apps/web/app/dashboard/tags/page.tsx b/apps/web/app/dashboard/tags/page.tsx
index 44c164e1..08acd968 100644
--- a/apps/web/app/dashboard/tags/page.tsx
+++ b/apps/web/app/dashboard/tags/page.tsx
@@ -1,15 +1,16 @@
+import Link from "next/link";
+import { redirect } from "next/navigation";
import { Separator } from "@/components/ui/separator";
import { getServerAuthSession } from "@/server/auth";
+import { count, eq } from "drizzle-orm";
+
import { db } from "@hoarder/db";
import { bookmarkTags, tagsOnBookmarks } from "@hoarder/db/schema";
-import { count, eq } from "drizzle-orm";
-import Link from "next/link";
-import { redirect } from "next/navigation";
function TagPill({ name, count }: { name: string; count: number }) {
return (
<Link
- className="text-foreground hover:bg-foreground hover:text-background flex gap-2 rounded-md border border-gray-200 bg-white px-2 py-1"
+ className="flex gap-2 rounded-md border border-gray-200 bg-white px-2 py-1 text-foreground hover:bg-foreground hover:text-background"
href={`/dashboard/tags/${name}`}
>
{name} <Separator orientation="vertical" /> {count}
diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx
index b1790a1f..6ec9c3e4 100644
--- a/apps/web/app/layout.tsx
+++ b/apps/web/app/layout.tsx
@@ -1,12 +1,14 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
+
import "./globals.css";
+
+import type { Viewport } from "next";
import React from "react";
import { Toaster } from "@/components/ui/toaster";
import Providers from "@/lib/providers";
-import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { getServerAuthSession } from "@/server/auth";
-import type { Viewport } from "next";
+import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
const inter = Inter({ subsets: ["latin"] });
diff --git a/apps/web/app/page.tsx b/apps/web/app/page.tsx
index f467b64b..ca076cbf 100644
--- a/apps/web/app/page.tsx
+++ b/apps/web/app/page.tsx
@@ -1,5 +1,5 @@
-import { getServerAuthSession } from "@/server/auth";
import { redirect } from "next/navigation";
+import { getServerAuthSession } from "@/server/auth";
export default async function Home() {
// TODO: Home currently just redirects between pages until we build a proper landing page
diff --git a/apps/web/app/signin/page.tsx b/apps/web/app/signin/page.tsx
index fed71b62..4dc81376 100644
--- a/apps/web/app/signin/page.tsx
+++ b/apps/web/app/signin/page.tsx
@@ -1,7 +1,7 @@
-import { PackageOpen } from "lucide-react";
-import SignInForm from "@/components/signin/SignInForm";
import { redirect } from "next/dist/client/components/navigation";
+import SignInForm from "@/components/signin/SignInForm";
import { getServerAuthSession } from "@/server/auth";
+import { PackageOpen } from "lucide-react";
export default async function SignInPage() {
const session = await getServerAuthSession();
diff --git a/apps/web/components/dashboard/bookmarks/AddLinkButton.tsx b/apps/web/components/dashboard/bookmarks/AddLinkButton.tsx
index 5973f909..45a67020 100644
--- a/apps/web/components/dashboard/bookmarks/AddLinkButton.tsx
+++ b/apps/web/components/dashboard/bookmarks/AddLinkButton.tsx
@@ -1,10 +1,5 @@
-import { Form, FormControl, FormField, FormItem } from "@/components/ui/form";
-import { Input } from "@/components/ui/input";
-import { useForm, SubmitErrorHandler } from "react-hook-form";
-import { z } from "zod";
-import { zodResolver } from "@hookform/resolvers/zod";
-import { toast } from "@/components/ui/use-toast";
-import { api } from "@/lib/trpc";
+import type { SubmitErrorHandler } from "react-hook-form";
+import { useState } from "react";
import { ActionButton } from "@/components/ui/action-button";
import { Button } from "@/components/ui/button";
import {
@@ -16,7 +11,13 @@ import {
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
-import { useState } from "react";
+import { Form, FormControl, FormField, FormItem } from "@/components/ui/form";
+import { Input } from "@/components/ui/input";
+import { toast } from "@/components/ui/use-toast";
+import { api } from "@/lib/trpc";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { useForm } from "react-hook-form";
+import { z } from "zod";
export function AddLinkButton({ children }: { children: React.ReactNode }) {
const [isOpen, setOpen] = useState(false);
diff --git a/apps/web/components/dashboard/bookmarks/AddToListModal.tsx b/apps/web/components/dashboard/bookmarks/AddToListModal.tsx
index c9fd5da0..6242aa27 100644
--- a/apps/web/components/dashboard/bookmarks/AddToListModal.tsx
+++ b/apps/web/components/dashboard/bookmarks/AddToListModal.tsx
@@ -1,3 +1,4 @@
+import { useState } from "react";
import { ActionButton } from "@/components/ui/action-button";
import { Button } from "@/components/ui/button";
import {
@@ -15,11 +16,6 @@ import {
FormItem,
FormMessage,
} from "@/components/ui/form";
-
-import { toast } from "@/components/ui/use-toast";
-import { api } from "@/lib/trpc";
-import { useState } from "react";
-
import {
Select,
SelectContent,
@@ -29,9 +25,11 @@ import {
SelectValue,
} from "@/components/ui/select";
import LoadingSpinner from "@/components/ui/spinner";
-import { z } from "zod";
-import { useForm } from "react-hook-form";
+import { toast } from "@/components/ui/use-toast";
+import { api } from "@/lib/trpc";
import { zodResolver } from "@hookform/resolvers/zod";
+import { useForm } from "react-hook-form";
+import { z } from "zod";
export default function AddToListModal({
bookmarkId,
@@ -115,12 +113,11 @@ export default function AddToListModal({
</SelectTrigger>
<SelectContent>
<SelectGroup>
- {lists &&
- lists.lists.map((l) => (
- <SelectItem key={l.id} value={l.id}>
- {l.icon} {l.name}
- </SelectItem>
- ))}
+ {lists?.lists.map((l) => (
+ <SelectItem key={l.id} value={l.id}>
+ {l.icon} {l.name}
+ </SelectItem>
+ ))}
</SelectGroup>
</SelectContent>
</Select>
diff --git a/apps/web/components/dashboard/bookmarks/BookmarkCardSkeleton.tsx b/apps/web/components/dashboard/bookmarks/BookmarkCardSkeleton.tsx
index 1f5fa433..026b8d37 100644
--- a/apps/web/components/dashboard/bookmarks/BookmarkCardSkeleton.tsx
+++ b/apps/web/components/dashboard/bookmarks/BookmarkCardSkeleton.tsx
@@ -1,10 +1,10 @@
import {
ImageCard,
+ ImageCardBanner,
ImageCardBody,
ImageCardContent,
ImageCardFooter,
ImageCardTitle,
- ImageCardBanner,
} from "@/components/ui/imageCard";
import { Skeleton } from "@/components/ui/skeleton";
diff --git a/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx b/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx
index 4f08ebee..3656a435 100644
--- a/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx
+++ b/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx
@@ -1,8 +1,6 @@
"use client";
-import { useToast } from "@/components/ui/use-toast";
-import { api } from "@/lib/trpc";
-import { ZBookmark, ZBookmarkedLink } from "@hoarder/trpc/types/bookmarks";
+import { useState } from "react";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
@@ -10,6 +8,8 @@ import {
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
+import { useToast } from "@/components/ui/use-toast";
+import { api } from "@/lib/trpc";
import {
Archive,
Link,
@@ -21,10 +21,12 @@ import {
Tags,
Trash2,
} from "lucide-react";
-import { useTagModel } from "./TagModal";
-import { useState } from "react";
-import { BookmarkedTextEditor } from "./BookmarkedTextEditor";
+
+import type { ZBookmark, ZBookmarkedLink } from "@hoarder/trpc/types/bookmarks";
+
import { useAddToListModal } from "./AddToListModal";
+import { BookmarkedTextEditor } from "./BookmarkedTextEditor";
+import { useTagModel } from "./TagModal";
export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
const { toast } = useToast();
diff --git a/apps/web/components/dashboard/bookmarks/BookmarkPreview.tsx b/apps/web/components/dashboard/bookmarks/BookmarkPreview.tsx
index 2a8ae1b1..69aa60a3 100644
--- a/apps/web/components/dashboard/bookmarks/BookmarkPreview.tsx
+++ b/apps/web/components/dashboard/bookmarks/BookmarkPreview.tsx
@@ -1,14 +1,15 @@
"use client";
+import Link from "next/link";
import { BackButton } from "@/components/ui/back-button";
import { Skeleton } from "@/components/ui/skeleton";
import { isBookmarkStillCrawling } from "@/lib/bookmarkUtils";
import { api } from "@/lib/trpc";
-import { ZBookmark } from "@hoarder/trpc/types/bookmarks";
import { ArrowLeftCircle, CalendarDays, ExternalLink } from "lucide-react";
-import Link from "next/link";
import Markdown from "react-markdown";
+import type { ZBookmark } from "@hoarder/trpc/types/bookmarks";
+
export default function BookmarkPreview({
initialData,
}: {
@@ -37,7 +38,7 @@ export default function BookmarkPreview({
const linkHeader = bookmark.content.type == "link" && (
<div className="flex flex-col space-y-2">
<p className="text-center text-3xl">
- {bookmark.content.title || bookmark.content.url}
+ {bookmark.content.title ?? bookmark.content.url}
</p>
<Link href={bookmark.content.url} className="mx-auto flex gap-2">
<span className="my-auto">View Original</span>
@@ -72,7 +73,7 @@ export default function BookmarkPreview({
}
return (
- <div className="bg-background m-4 min-h-screen space-y-4 rounded-md border p-4">
+ <div className="m-4 min-h-screen space-y-4 rounded-md border bg-background p-4">
<div className="flex justify-between">
<BackButton className="ghost" variant="ghost">
<ArrowLeftCircle />
diff --git a/apps/web/components/dashboard/bookmarks/BookmarkedTextEditor.tsx b/apps/web/components/dashboard/bookmarks/BookmarkedTextEditor.tsx
index a5b58f1a..eb618474 100644
--- a/apps/web/components/dashboard/bookmarks/BookmarkedTextEditor.tsx
+++ b/apps/web/components/dashboard/bookmarks/BookmarkedTextEditor.tsx
@@ -1,4 +1,6 @@
-import { ZBookmark } from "@hoarder/trpc/types/bookmarks";
+import { useState } from "react";
+import { ActionButton } from "@/components/ui/action-button";
+import { Button } from "@/components/ui/button";
import {
Dialog,
DialogClose,
@@ -8,12 +10,11 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
-import { ActionButton } from "@/components/ui/action-button";
-import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
-import { api } from "@/lib/trpc";
-import { useState } from "react";
import { toast } from "@/components/ui/use-toast";
+import { api } from "@/lib/trpc";
+
+import type { ZBookmark } from "@hoarder/trpc/types/bookmarks";
export function BookmarkedTextEditor({
bookmark,
diff --git a/apps/web/components/dashboard/bookmarks/Bookmarks.tsx b/apps/web/components/dashboard/bookmarks/Bookmarks.tsx
index 1ad3670c..9f001551 100644
--- a/apps/web/components/dashboard/bookmarks/Bookmarks.tsx
+++ b/apps/web/components/dashboard/bookmarks/Bookmarks.tsx
@@ -1,9 +1,11 @@
import { redirect } from "next/navigation";
-import BookmarksGrid from "./BookmarksGrid";
-import { ZGetBookmarksRequest } from "@hoarder/trpc/types/bookmarks";
import { api } from "@/server/api/client";
import { getServerAuthSession } from "@/server/auth";
+import type { ZGetBookmarksRequest } from "@hoarder/trpc/types/bookmarks";
+
+import BookmarksGrid from "./BookmarksGrid";
+
export default async function Bookmarks({
favourited,
archived,
diff --git a/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx b/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx
index 4d5b6b0a..dd529a8b 100644
--- a/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx
+++ b/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx
@@ -1,14 +1,19 @@
"use client";
-import LinkCard from "./LinkCard";
-import { ZBookmark, ZGetBookmarksRequest } from "@hoarder/trpc/types/bookmarks";
+import { useMemo } from "react";
import { api } from "@/lib/trpc";
-import TextCard from "./TextCard";
+import tailwindConfig from "@/tailwind.config";
import { Slot } from "@radix-ui/react-slot";
import Masonry from "react-masonry-css";
import resolveConfig from "tailwindcss/resolveConfig";
-import tailwindConfig from "@/tailwind.config";
-import { useMemo } from "react";
+
+import type {
+ ZBookmark,
+ ZGetBookmarksRequest,
+} from "@hoarder/trpc/types/bookmarks";
+
+import LinkCard from "./LinkCard";
+import TextCard from "./TextCard";
function getBreakpointConfig() {
const fullConfig = resolveConfig(tailwindConfig);
diff --git a/apps/web/components/dashboard/bookmarks/LinkCard.tsx b/apps/web/components/dashboard/bookmarks/LinkCard.tsx
index 50f30e47..808e6d91 100644
--- a/apps/web/components/dashboard/bookmarks/LinkCard.tsx
+++ b/apps/web/components/dashboard/bookmarks/LinkCard.tsx
@@ -1,5 +1,6 @@
"use client";
+import Link from "next/link";
import {
ImageCard,
ImageCardBanner,
@@ -8,17 +9,18 @@ import {
ImageCardFooter,
ImageCardTitle,
} from "@/components/ui/imageCard";
-import { ZBookmark } from "@hoarder/trpc/types/bookmarks";
-import Link from "next/link";
-import BookmarkOptions from "./BookmarkOptions";
-import { api } from "@/lib/trpc";
-import { Maximize2, Star } from "lucide-react";
-import TagList from "./TagList";
import {
isBookmarkStillCrawling,
isBookmarkStillLoading,
isBookmarkStillTagging,
} from "@/lib/bookmarkUtils";
+import { api } from "@/lib/trpc";
+import { Maximize2, Star } from "lucide-react";
+
+import type { ZBookmark } from "@hoarder/trpc/types/bookmarks";
+
+import BookmarkOptions from "./BookmarkOptions";
+import TagList from "./TagList";
export default function LinkCard({
bookmark: initialData,
diff --git a/apps/web/components/dashboard/bookmarks/TagList.tsx b/apps/web/components/dashboard/bookmarks/TagList.tsx
index 6c9d2d22..cb94e5d7 100644
--- a/apps/web/components/dashboard/bookmarks/TagList.tsx
+++ b/apps/web/components/dashboard/bookmarks/TagList.tsx
@@ -1,9 +1,10 @@
-import { badgeVariants } from "@/components/ui/badge";
import Link from "next/link";
+import { badgeVariants } from "@/components/ui/badge";
import { Skeleton } from "@/components/ui/skeleton";
-import { ZBookmark } from "@hoarder/trpc/types/bookmarks";
import { cn } from "@/lib/utils";
+import type { ZBookmark } from "@hoarder/trpc/types/bookmarks";
+
export default function TagList({
bookmark,
loading,
@@ -26,7 +27,7 @@ export default function TagList({
<Link
className={cn(
badgeVariants({ variant: "outline" }),
- "hover:bg-foreground hover:text-secondary text-nowrap",
+ "text-nowrap hover:bg-foreground hover:text-secondary",
)}
href={`/dashboard/tags/${t.name}`}
>
diff --git a/apps/web/components/dashboard/bookmarks/TagModal.tsx b/apps/web/components/dashboard/bookmarks/TagModal.tsx
index 8c09d00e..367e6e7d 100644
--- a/apps/web/components/dashboard/bookmarks/TagModal.tsx
+++ b/apps/web/components/dashboard/bookmarks/TagModal.tsx
@@ -1,3 +1,5 @@
+import type { KeyboardEvent } from "react";
+import { useEffect, useState } from "react";
import { ActionButton } from "@/components/ui/action-button";
import { Button } from "@/components/ui/button";
import {
@@ -11,13 +13,17 @@ import {
import { Input } from "@/components/ui/input";
import { toast } from "@/components/ui/use-toast";
import { api } from "@/lib/trpc";
-import { ZBookmark } from "@hoarder/trpc/types/bookmarks";
-import { ZAttachedByEnum } from "@hoarder/trpc/types/tags";
import { cn } from "@/lib/utils";
import { Sparkles, X } from "lucide-react";
-import { useState, KeyboardEvent, useEffect } from "react";
-type EditableTag = { attachedBy: ZAttachedByEnum; id?: string; name: string };
+import type { ZBookmark } from "@hoarder/trpc/types/bookmarks";
+import type { ZAttachedByEnum } from "@hoarder/trpc/types/tags";
+
+interface EditableTag {
+ attachedBy: ZAttachedByEnum;
+ id?: string;
+ name: string;
+}
function TagAddInput({ addTag }: { addTag: (tag: string) => void }) {
const onKeyUp = (e: KeyboardEvent<HTMLInputElement>) => {
diff --git a/apps/web/components/dashboard/bookmarks/TextCard.tsx b/apps/web/components/dashboard/bookmarks/TextCard.tsx
index 2565e69d..5028c1bb 100644
--- a/apps/web/components/dashboard/bookmarks/TextCard.tsx
+++ b/apps/web/components/dashboard/bookmarks/TextCard.tsx
@@ -1,16 +1,18 @@
"use client";
-import { ZBookmark } from "@hoarder/trpc/types/bookmarks";
-import BookmarkOptions from "./BookmarkOptions";
+import { useState } from "react";
+import Link from "next/link";
+import { isBookmarkStillTagging } from "@/lib/bookmarkUtils";
import { api } from "@/lib/trpc";
-import { Maximize2, Star } from "lucide-react";
import { cn } from "@/lib/utils";
-import TagList from "./TagList";
+import { Maximize2, Star } from "lucide-react";
import Markdown from "react-markdown";
-import { useState } from "react";
+
+import type { ZBookmark } from "@hoarder/trpc/types/bookmarks";
+
import { BookmarkedTextViewer } from "./BookmarkedTextViewer";
-import Link from "next/link";
-import { isBookmarkStillTagging } from "@/lib/bookmarkUtils";
+import BookmarkOptions from "./BookmarkOptions";
+import TagList from "./TagList";
export default function TextCard({
bookmark: initialData,
diff --git a/apps/web/components/dashboard/bookmarks/TopNav.tsx b/apps/web/components/dashboard/bookmarks/TopNav.tsx
index 6c0f18e5..4274762c 100644
--- a/apps/web/components/dashboard/bookmarks/TopNav.tsx
+++ b/apps/web/components/dashboard/bookmarks/TopNav.tsx
@@ -1,11 +1,12 @@
"use client";
-import { Link, NotebookPen } from "lucide-react";
-import { Button } from "@/components/ui/button";
-import { BookmarkedTextEditor } from "./BookmarkedTextEditor";
import { useState } from "react";
-import { AddLinkButton } from "./AddLinkButton";
+import { Button } from "@/components/ui/button";
+import { Link, NotebookPen } from "lucide-react";
+
import { SearchInput } from "../search/SearchInput";
+import { AddLinkButton } from "./AddLinkButton";
+import { BookmarkedTextEditor } from "./BookmarkedTextEditor";
function AddText() {
const [isEditorOpen, setEditorOpen] = useState(false);
diff --git a/apps/web/components/dashboard/lists/AllListsView.tsx b/apps/web/components/dashboard/lists/AllListsView.tsx
index 81f31cde..acb94edb 100644
--- a/apps/web/components/dashboard/lists/AllListsView.tsx
+++ b/apps/web/components/dashboard/lists/AllListsView.tsx
@@ -1,12 +1,13 @@
"use client";
+import Link from "next/link";
+import { useNewListModal } from "@/components/dashboard/sidebar/NewListModal";
import { Button } from "@/components/ui/button";
import { api } from "@/lib/trpc";
-import { ZBookmarkList } from "@hoarder/trpc/types/lists";
import { keepPreviousData } from "@tanstack/react-query";
import { Plus } from "lucide-react";
-import Link from "next/link";
-import { useNewListModal } from "@/components/dashboard/sidebar/NewListModal";
+
+import type { ZBookmarkList } from "@hoarder/trpc/types/lists";
function ListItem({
name,
@@ -19,7 +20,7 @@ function ListItem({
}) {
return (
<Link href={path}>
- <div className="bg-background rounded-md border border-gray-200 px-4 py-2 text-lg">
+ <div className="rounded-md border border-gray-200 bg-background px-4 py-2 text-lg">
<p className="text-nowrap">
{icon} {name}
</p>
diff --git a/apps/web/components/dashboard/lists/DeleteListButton.tsx b/apps/web/components/dashboard/lists/DeleteListButton.tsx
index 5303b217..f5fcb18b 100644
--- a/apps/web/components/dashboard/lists/DeleteListButton.tsx
+++ b/apps/web/components/dashboard/lists/DeleteListButton.tsx
@@ -1,5 +1,8 @@
"use client";
+import { useState } from "react";
+import { useRouter } from "next/navigation";
+import { ActionButton } from "@/components/ui/action-button";
import { Button } from "@/components/ui/button";
import {
Dialog,
@@ -10,13 +13,11 @@ import {
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
-import { Trash } from "lucide-react";
-import { useRouter } from "next/navigation";
import { toast } from "@/components/ui/use-toast";
import { api } from "@/lib/trpc";
-import { ActionButton } from "@/components/ui/action-button";
-import { useState } from "react";
-import { ZBookmarkList } from "@hoarder/trpc/types/lists";
+import { Trash } from "lucide-react";
+
+import type { ZBookmarkList } from "@hoarder/trpc/types/lists";
export default function DeleteListButton({ list }: { list: ZBookmarkList }) {
const [isDialogOpen, setDialogOpen] = useState(false);
diff --git a/apps/web/components/dashboard/lists/ListView.tsx b/apps/web/components/dashboard/lists/ListView.tsx
index 2d48d9e3..beeea7f1 100644
--- a/apps/web/components/dashboard/lists/ListView.tsx
+++ b/apps/web/components/dashboard/lists/ListView.tsx
@@ -1,10 +1,11 @@
"use client";
import BookmarksGrid from "@/components/dashboard/bookmarks/BookmarksGrid";
-import { ZBookmark } from "@hoarder/trpc/types/bookmarks";
-import { ZBookmarkListWithBookmarks } from "@hoarder/trpc/types/lists";
import { api } from "@/lib/trpc";
+import type { ZBookmark } from "@hoarder/trpc/types/bookmarks";
+import type { ZBookmarkListWithBookmarks } from "@hoarder/trpc/types/lists";
+
export default function ListView({
bookmarks,
list: initialData,
diff --git a/apps/web/components/dashboard/search/SearchInput.tsx b/apps/web/components/dashboard/search/SearchInput.tsx
index 73d14c90..abb19f5e 100644
--- a/apps/web/components/dashboard/search/SearchInput.tsx
+++ b/apps/web/components/dashboard/search/SearchInput.tsx
@@ -1,7 +1,7 @@
+import React from "react";
import { Input } from "@/components/ui/input";
import { useDoBookmarkSearch } from "@/lib/hooks/bookmark-search";
import { cn } from "@/lib/utils";
-import React from "react";
const SearchInput = React.forwardRef<
HTMLInputElement,
diff --git a/apps/web/components/dashboard/settings/AddApiKey.tsx b/apps/web/components/dashboard/settings/AddApiKey.tsx
index a4fd9c25..15a78d56 100644
--- a/apps/web/components/dashboard/settings/AddApiKey.tsx
+++ b/apps/web/components/dashboard/settings/AddApiKey.tsx
@@ -1,17 +1,10 @@
"use client";
+import type { SubmitErrorHandler } from "react-hook-form";
+import { useState } from "react";
+import { useRouter } from "next/navigation";
+import { ActionButton } from "@/components/ui/action-button";
import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import {
- Form,
- FormControl,
- FormDescription,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
-} from "@/components/ui/form";
-
import {
Dialog,
DialogClose,
@@ -22,15 +15,22 @@ import {
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
-import { z } from "zod";
-import { useRouter } from "next/navigation";
-import { zodResolver } from "@hookform/resolvers/zod";
-import { useForm, SubmitErrorHandler } from "react-hook-form";
+import {
+ Form,
+ FormControl,
+ FormDescription,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from "@/components/ui/form";
+import { Input } from "@/components/ui/input";
import { toast } from "@/components/ui/use-toast";
import { api } from "@/lib/trpc";
-import { useState } from "react";
+import { zodResolver } from "@hookform/resolvers/zod";
import { Check, Copy } from "lucide-react";
-import { ActionButton } from "@/components/ui/action-button";
+import { useForm } from "react-hook-form";
+import { z } from "zod";
function ApiKeySuccess({ apiKey }: { apiKey: string }) {
const [isCopied, setCopied] = useState(false);
diff --git a/apps/web/components/dashboard/settings/ApiKeySettings.tsx b/apps/web/components/dashboard/settings/ApiKeySettings.tsx
index 1598f25f..a3680863 100644
--- a/apps/web/components/dashboard/settings/ApiKeySettings.tsx
+++ b/apps/web/components/dashboard/settings/ApiKeySettings.tsx
@@ -7,8 +7,9 @@ import {
TableRow,
} from "@/components/ui/table";
import { api } from "@/server/api/client";
-import DeleteApiKey from "./DeleteApiKey";
+
import AddApiKey from "./AddApiKey";
+import DeleteApiKey from "./DeleteApiKey";
export default async function ApiKeys() {
const keys = await api.apiKeys.list();
diff --git a/apps/web/components/dashboard/settings/DeleteApiKey.tsx b/apps/web/components/dashboard/settings/DeleteApiKey.tsx
index 566136af..091f352c 100644
--- a/apps/web/components/dashboard/settings/DeleteApiKey.tsx
+++ b/apps/web/components/dashboard/settings/DeleteApiKey.tsx
@@ -1,8 +1,9 @@
"use client";
+import { useState } from "react";
+import { useRouter } from "next/navigation";
+import { ActionButton } from "@/components/ui/action-button";
import { Button } from "@/components/ui/button";
-import { Trash } from "lucide-react";
-
import {
Dialog,
DialogClose,
@@ -13,11 +14,9 @@ import {
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
-import { useRouter } from "next/navigation";
import { toast } from "@/components/ui/use-toast";
import { api } from "@/lib/trpc";
-import { ActionButton } from "@/components/ui/action-button";
-import { useState } from "react";
+import { Trash } from "lucide-react";
export default function DeleteApiKey({
name,
diff --git a/apps/web/components/dashboard/sidebar/AllLists.tsx b/apps/web/components/dashboard/sidebar/AllLists.tsx
index a77252d0..34680cdd 100644
--- a/apps/web/components/dashboard/sidebar/AllLists.tsx
+++ b/apps/web/components/dashboard/sidebar/AllLists.tsx
@@ -1,11 +1,13 @@
"use client";
+import Link from "next/link";
import { api } from "@/lib/trpc";
-import SidebarItem from "./SidebarItem";
-import NewListModal, { useNewListModal } from "./NewListModal";
import { Plus } from "lucide-react";
-import Link from "next/link";
-import { ZBookmarkList } from "@hoarder/trpc/types/lists";
+
+import type { ZBookmarkList } from "@hoarder/trpc/types/lists";
+
+import NewListModal, { useNewListModal } from "./NewListModal";
+import SidebarItem from "./SidebarItem";
export default function AllLists({
initialData,
diff --git a/apps/web/components/dashboard/sidebar/ModileSidebar.tsx b/apps/web/components/dashboard/sidebar/ModileSidebar.tsx
index 4bd6a347..3c68433a 100644
--- a/apps/web/components/dashboard/sidebar/ModileSidebar.tsx
+++ b/apps/web/components/dashboard/sidebar/ModileSidebar.tsx
@@ -1,11 +1,12 @@
-import MobileSidebarItem from "./ModileSidebarItem";
import {
- Tag,
+ ClipboardList,
PackageOpen,
- Settings,
Search,
- ClipboardList,
+ Settings,
+ Tag,
} from "lucide-react";
+
+import MobileSidebarItem from "./ModileSidebarItem";
import SidebarProfileOptions from "./SidebarProfileOptions";
export default async function MobileSidebar() {
diff --git a/apps/web/components/dashboard/sidebar/ModileSidebarItem.tsx b/apps/web/components/dashboard/sidebar/ModileSidebarItem.tsx
index 9389d2e4..d2b4aad3 100644
--- a/apps/web/components/dashboard/sidebar/ModileSidebarItem.tsx
+++ b/apps/web/components/dashboard/sidebar/ModileSidebarItem.tsx
@@ -1,8 +1,8 @@
"use client";
-import { cn } from "@/lib/utils";
import Link from "next/link";
import { usePathname } from "next/navigation";
+import { cn } from "@/lib/utils";
export default function MobileSidebarItem({
logo,
diff --git a/apps/web/components/dashboard/sidebar/NewListModal.tsx b/apps/web/components/dashboard/sidebar/NewListModal.tsx
index f51616ed..e244411d 100644
--- a/apps/web/components/dashboard/sidebar/NewListModal.tsx
+++ b/apps/web/components/dashboard/sidebar/NewListModal.tsx
@@ -1,14 +1,5 @@
"use client";
-import data from "@emoji-mart/data";
-import Picker from "@emoji-mart/react";
-
-import {
- Popover,
- PopoverContent,
- PopoverTrigger,
-} from "@/components/ui/popover";
-
import { ActionButton } from "@/components/ui/action-button";
import { Button } from "@/components/ui/button";
import {
@@ -18,7 +9,6 @@ import {
DialogFooter,
DialogHeader,
DialogTitle,
- DialogTrigger,
} from "@/components/ui/dialog";
import {
Form,
@@ -27,15 +17,19 @@ import {
FormItem,
FormMessage,
} from "@/components/ui/form";
-
+import { Input } from "@/components/ui/input";
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover";
import { toast } from "@/components/ui/use-toast";
import { api } from "@/lib/trpc";
-
-import { z } from "zod";
-import { useForm } from "react-hook-form";
+import data from "@emoji-mart/data";
+import Picker from "@emoji-mart/react";
import { zodResolver } from "@hookform/resolvers/zod";
-import { Input } from "@/components/ui/input";
-
+import { useForm } from "react-hook-form";
+import { z } from "zod";
import { create } from "zustand";
export const useNewListModal = create<{
@@ -113,7 +107,7 @@ export default function NewListModal() {
<FormItem>
<FormControl>
<Popover>
- <PopoverTrigger className="border-input h-full rounded border px-2 text-2xl">
+ <PopoverTrigger className="h-full rounded border border-input px-2 text-2xl">
{field.value}
</PopoverTrigger>
<PopoverContent>
diff --git a/apps/web/components/dashboard/sidebar/Sidebar.tsx b/apps/web/components/dashboard/sidebar/Sidebar.tsx
index a5c1d7a5..0351b889 100644
--- a/apps/web/components/dashboard/sidebar/Sidebar.tsx
+++ b/apps/web/components/dashboard/sidebar/Sidebar.tsx
@@ -1,13 +1,15 @@
-import { Tag, Home, PackageOpen, Settings, Search, Shield } from "lucide-react";
-import { redirect } from "next/navigation";
-import SidebarItem from "./SidebarItem";
-import { getServerAuthSession } from "@/server/auth";
import Link from "next/link";
-import SidebarProfileOptions from "./SidebarProfileOptions";
+import { redirect } from "next/navigation";
import { Separator } from "@/components/ui/separator";
-import AllLists from "./AllLists";
-import serverConfig from "@hoarder/shared/config";
import { api } from "@/server/api/client";
+import { getServerAuthSession } from "@/server/auth";
+import { Home, PackageOpen, Search, Settings, Shield, Tag } from "lucide-react";
+
+import serverConfig from "@hoarder/shared/config";
+
+import AllLists from "./AllLists";
+import SidebarItem from "./SidebarItem";
+import SidebarProfileOptions from "./SidebarProfileOptions";
export default async function Sidebar() {
const session = await getServerAuthSession();
diff --git a/apps/web/components/dashboard/sidebar/SidebarItem.tsx b/apps/web/components/dashboard/sidebar/SidebarItem.tsx
index 856bdffd..75a1f6ba 100644
--- a/apps/web/components/dashboard/sidebar/SidebarItem.tsx
+++ b/apps/web/components/dashboard/sidebar/SidebarItem.tsx
@@ -1,8 +1,8 @@
"use client";
-import { cn } from "@/lib/utils";
import Link from "next/link";
import { usePathname } from "next/navigation";
+import { cn } from "@/lib/utils";
export default function SidebarItem({
name,
diff --git a/apps/web/components/signin/CredentialsForm.tsx b/apps/web/components/signin/CredentialsForm.tsx
index 5296e163..59dfeb21 100644
--- a/apps/web/components/signin/CredentialsForm.tsx
+++ b/apps/web/components/signin/CredentialsForm.tsx
@@ -1,8 +1,8 @@
"use client";
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
-import { zodResolver } from "@hookform/resolvers/zod";
-import { useForm } from "react-hook-form";
-import { z } from "zod";
+
+import { useState } from "react";
+import { useRouter } from "next/navigation";
+import { ActionButton } from "@/components/ui/action-button";
import {
Form,
FormControl,
@@ -12,13 +12,15 @@ import {
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
-import { ActionButton } from "@/components/ui/action-button";
-import { zSignUpSchema } from "@hoarder/trpc/types/users";
-import { signIn } from "next-auth/react";
-import { useState } from "react";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { api } from "@/lib/trpc";
-import { useRouter } from "next/navigation";
+import { zodResolver } from "@hookform/resolvers/zod";
import { TRPCClientError } from "@trpc/client";
+import { signIn } from "next-auth/react";
+import { useForm } from "react-hook-form";
+import { z } from "zod";
+
+import { zSignUpSchema } from "@hoarder/trpc/types/users";
const signInSchema = z.object({
email: z.string().email(),
diff --git a/apps/web/components/signin/SignInForm.tsx b/apps/web/components/signin/SignInForm.tsx
index 7c8f8936..aa70e207 100644
--- a/apps/web/components/signin/SignInForm.tsx
+++ b/apps/web/components/signin/SignInForm.tsx
@@ -1,6 +1,7 @@
import { getProviders } from "next-auth/react";
-import SignInProviderButton from "./SignInProviderButton";
+
import CredentialsForm from "./CredentialsForm";
+import SignInProviderButton from "./SignInProviderButton";
export default async function SignInForm() {
const providers = await getProviders();
diff --git a/apps/web/components/signin/SignInProviderButton.tsx b/apps/web/components/signin/SignInProviderButton.tsx
index 0831236c..0f208397 100644
--- a/apps/web/components/signin/SignInProviderButton.tsx
+++ b/apps/web/components/signin/SignInProviderButton.tsx
@@ -1,6 +1,8 @@
"use client";
+
+import type { ClientSafeProvider } from "next-auth/react";
import { Button } from "@/components/ui/button";
-import { ClientSafeProvider, signIn } from "next-auth/react";
+import { signIn } from "next-auth/react";
export default function SignInProviderButton({
provider,
diff --git a/apps/web/components/ui/action-button.tsx b/apps/web/components/ui/action-button.tsx
index 42e16f65..11b02a5f 100644
--- a/apps/web/components/ui/action-button.tsx
+++ b/apps/web/components/ui/action-button.tsx
@@ -1,4 +1,5 @@
-import { Button, ButtonProps } from "./button";
+import type { ButtonProps } from "./button";
+import { Button } from "./button";
import LoadingSpinner from "./spinner";
export function ActionButton({
diff --git a/apps/web/components/ui/back-button.tsx b/apps/web/components/ui/back-button.tsx
index 685930df..46c99f7c 100644
--- a/apps/web/components/ui/back-button.tsx
+++ b/apps/web/components/ui/back-button.tsx
@@ -1,7 +1,9 @@
"use client";
import { useRouter } from "next/navigation";
-import { Button, ButtonProps } from "./button";
+
+import type { ButtonProps } from "./button";
+import { Button } from "./button";
export function BackButton({ ...props }: ButtonProps) {
const router = useRouter();
diff --git a/apps/web/components/ui/badge.tsx b/apps/web/components/ui/badge.tsx
index c30daca1..7950a5ee 100644
--- a/apps/web/components/ui/badge.tsx
+++ b/apps/web/components/ui/badge.tsx
@@ -1,19 +1,19 @@
+import type { VariantProps } from "class-variance-authority";
import * as React from "react";
-import { cva, type VariantProps } from "class-variance-authority";
-
import { cn } from "@/lib/utils";
+import { cva } from "class-variance-authority";
const badgeVariants = cva(
- "focus:ring-ring inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2",
+ "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
variants: {
variant: {
default:
- "bg-primary text-primary-foreground hover:bg-primary/80 border-transparent",
+ "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
secondary:
- "bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent",
+ "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive:
- "bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent",
+ "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground",
},
},
diff --git a/apps/web/components/ui/button.tsx b/apps/web/components/ui/button.tsx
index 79b45fa0..5ed8df91 100644
--- a/apps/web/components/ui/button.tsx
+++ b/apps/web/components/ui/button.tsx
@@ -1,11 +1,11 @@
+import type { VariantProps } from "class-variance-authority";
import * as React from "react";
-import { Slot } from "@radix-ui/react-slot";
-import { cva, type VariantProps } from "class-variance-authority";
-
import { cn } from "@/lib/utils";
+import { Slot } from "@radix-ui/react-slot";
+import { cva } from "class-variance-authority";
const buttonVariants = cva(
- "ring-offset-background focus-visible:ring-ring inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
@@ -13,7 +13,7 @@ const buttonVariants = cva(
destructive:
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
- "border-input bg-background hover:bg-accent hover:text-accent-foreground border",
+ "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
diff --git a/apps/web/components/ui/card.tsx b/apps/web/components/ui/card.tsx
index f4e57996..9df66460 100644
--- a/apps/web/components/ui/card.tsx
+++ b/apps/web/components/ui/card.tsx
@@ -1,5 +1,4 @@
import * as React from "react";
-
import { cn } from "@/lib/utils";
const Card = React.forwardRef<
@@ -9,7 +8,7 @@ const Card = React.forwardRef<
<div
ref={ref}
className={cn(
- "bg-card text-card-foreground rounded-lg border shadow-sm",
+ "rounded-lg border bg-card text-card-foreground shadow-sm",
className,
)}
{...props}
@@ -33,6 +32,7 @@ const CardTitle = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
+ // eslint-disable-next-line jsx-a11y/heading-has-content
<h3
ref={ref}
className={cn(
@@ -50,7 +50,7 @@ const CardDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
<p
ref={ref}
- className={cn("text-muted-foreground text-sm", className)}
+ className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
));
diff --git a/apps/web/components/ui/dialog.tsx b/apps/web/components/ui/dialog.tsx
index 8fe3fe35..8e0c3c6c 100644
--- a/apps/web/components/ui/dialog.tsx
+++ b/apps/web/components/ui/dialog.tsx
@@ -1,11 +1,10 @@
"use client";
import * as React from "react";
+import { cn } from "@/lib/utils";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { X } from "lucide-react";
-import { cn } from "@/lib/utils";
-
const Dialog = DialogPrimitive.Root;
const DialogTrigger = DialogPrimitive.Trigger;
@@ -21,7 +20,7 @@ const DialogOverlay = React.forwardRef<
<DialogPrimitive.Overlay
ref={ref}
className={cn(
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className,
)}
{...props}
@@ -38,13 +37,13 @@ const DialogContent = React.forwardRef<
<DialogPrimitive.Content
ref={ref}
className={cn(
- "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg",
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
className,
)}
{...props}
>
{children}
- <DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none">
+ <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
<X className="size-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
@@ -102,7 +101,7 @@ const DialogDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
<DialogPrimitive.Description
ref={ref}
- className={cn("text-muted-foreground text-sm", className)}
+ className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
));
diff --git a/apps/web/components/ui/dropdown-menu.tsx b/apps/web/components/ui/dropdown-menu.tsx
index 3a9a2ff7..2bab577e 100644
--- a/apps/web/components/ui/dropdown-menu.tsx
+++ b/apps/web/components/ui/dropdown-menu.tsx
@@ -1,11 +1,10 @@
"use client";
import * as React from "react";
+import { cn } from "@/lib/utils";
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
import { Check, ChevronRight, Circle } from "lucide-react";
-import { cn } from "@/lib/utils";
-
const DropdownMenu = DropdownMenuPrimitive.Root;
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
@@ -27,7 +26,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
<DropdownMenuPrimitive.SubTrigger
ref={ref}
className={cn(
- "focus:bg-accent data-[state=open]:bg-accent flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none",
+ "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
inset && "pl-8",
className,
)}
@@ -47,7 +46,7 @@ const DropdownMenuSubContent = React.forwardRef<
<DropdownMenuPrimitive.SubContent
ref={ref}
className={cn(
- "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-lg",
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}
@@ -65,7 +64,7 @@ const DropdownMenuContent = React.forwardRef<
ref={ref}
sideOffset={sideOffset}
className={cn(
- "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md",
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}
@@ -83,7 +82,7 @@ const DropdownMenuItem = React.forwardRef<
<DropdownMenuPrimitive.Item
ref={ref}
className={cn(
- "focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
+ "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
inset && "pl-8",
className,
)}
@@ -99,7 +98,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
<DropdownMenuPrimitive.CheckboxItem
ref={ref}
className={cn(
- "focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className,
)}
checked={checked}
@@ -123,7 +122,7 @@ const DropdownMenuRadioItem = React.forwardRef<
<DropdownMenuPrimitive.RadioItem
ref={ref}
className={cn(
- "focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className,
)}
{...props}
@@ -162,7 +161,7 @@ const DropdownMenuSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.Separator
ref={ref}
- className={cn("bg-muted -mx-1 my-1 h-px", className)}
+ className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props}
/>
));
diff --git a/apps/web/components/ui/form.tsx b/apps/web/components/ui/form.tsx
index e62e10e9..20ce3c4b 100644
--- a/apps/web/components/ui/form.tsx
+++ b/apps/web/components/ui/form.tsx
@@ -1,26 +1,19 @@
+import type * as LabelPrimitive from "@radix-ui/react-label";
+import type { ControllerProps, FieldPath, FieldValues } from "react-hook-form";
import * as React from "react";
-import * as LabelPrimitive from "@radix-ui/react-label";
-import { Slot } from "@radix-ui/react-slot";
-import {
- Controller,
- ControllerProps,
- FieldPath,
- FieldValues,
- FormProvider,
- useFormContext,
-} from "react-hook-form";
-
-import { cn } from "@/lib/utils";
import { Label } from "@/components/ui/label";
+import { cn } from "@/lib/utils";
+import { Slot } from "@radix-ui/react-slot";
+import { Controller, FormProvider, useFormContext } from "react-hook-form";
const Form = FormProvider;
-type FormFieldContextValue<
+interface FormFieldContextValue<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
-> = {
+> {
name: TName;
-};
+}
const FormFieldContext = React.createContext<FormFieldContextValue>(
{} as FormFieldContextValue,
@@ -62,9 +55,9 @@ const useFormField = () => {
};
};
-type FormItemContextValue = {
+interface FormItemContextValue {
id: string;
-};
+}
const FormItemContext = React.createContext<FormItemContextValue>(
{} as FormItemContextValue,
@@ -134,7 +127,7 @@ const FormDescription = React.forwardRef<
<p
ref={ref}
id={formDescriptionId}
- className={cn("text-muted-foreground text-sm", className)}
+ className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
);
@@ -156,7 +149,7 @@ const FormMessage = React.forwardRef<
<p
ref={ref}
id={formMessageId}
- className={cn("text-destructive text-sm font-medium", className)}
+ className={cn("text-sm font-medium text-destructive", className)}
{...props}
>
{body}
diff --git a/apps/web/components/ui/imageCard.tsx b/apps/web/components/ui/imageCard.tsx
index f10ebdb5..e4941733 100644
--- a/apps/web/components/ui/imageCard.tsx
+++ b/apps/web/components/ui/imageCard.tsx
@@ -1,5 +1,4 @@
import * as React from "react";
-
import { cn } from "@/lib/utils";
export function ImageCard({
diff --git a/apps/web/components/ui/input.tsx b/apps/web/components/ui/input.tsx
index 21aac7ad..5543446c 100644
--- a/apps/web/components/ui/input.tsx
+++ b/apps/web/components/ui/input.tsx
@@ -1,9 +1,7 @@
import * as React from "react";
-
import { cn } from "@/lib/utils";
-export interface InputProps
- extends React.InputHTMLAttributes<HTMLInputElement> {}
+export type InputProps = React.InputHTMLAttributes<HTMLInputElement>;
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
@@ -11,7 +9,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
<input
type={type}
className={cn(
- "border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
+ "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
ref={ref}
diff --git a/apps/web/components/ui/label.tsx b/apps/web/components/ui/label.tsx
index 84f8b0c7..d12e2c2c 100644
--- a/apps/web/components/ui/label.tsx
+++ b/apps/web/components/ui/label.tsx
@@ -1,10 +1,10 @@
"use client";
+import type { VariantProps } from "class-variance-authority";
import * as React from "react";
-import * as LabelPrimitive from "@radix-ui/react-label";
-import { cva, type VariantProps } from "class-variance-authority";
-
import { cn } from "@/lib/utils";
+import * as LabelPrimitive from "@radix-ui/react-label";
+import { cva } from "class-variance-authority";
const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
diff --git a/apps/web/components/ui/popover.tsx b/apps/web/components/ui/popover.tsx
index a361ba7d..30645cc8 100644
--- a/apps/web/components/ui/popover.tsx
+++ b/apps/web/components/ui/popover.tsx
@@ -1,9 +1,8 @@
"use client";
import * as React from "react";
-import * as PopoverPrimitive from "@radix-ui/react-popover";
-
import { cn } from "@/lib/utils";
+import * as PopoverPrimitive from "@radix-ui/react-popover";
const Popover = PopoverPrimitive.Root;
@@ -19,7 +18,7 @@ const PopoverContent = React.forwardRef<
align={align}
sideOffset={sideOffset}
className={cn(
- "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border p-4 shadow-md outline-none",
+ "z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}
diff --git a/apps/web/components/ui/scroll-area.tsx b/apps/web/components/ui/scroll-area.tsx
index 32cb6022..9d77ecd1 100644
--- a/apps/web/components/ui/scroll-area.tsx
+++ b/apps/web/components/ui/scroll-area.tsx
@@ -1,9 +1,8 @@
"use client";
import * as React from "react";
-import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
-
import { cn } from "@/lib/utils";
+import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
@@ -40,7 +39,7 @@ const ScrollBar = React.forwardRef<
)}
{...props}
>
- <ScrollAreaPrimitive.ScrollAreaThumb className="bg-border relative flex-1 rounded-full" />
+ <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
</ScrollAreaPrimitive.ScrollAreaScrollbar>
));
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
diff --git a/apps/web/components/ui/select.tsx b/apps/web/components/ui/select.tsx
index efd4ff1e..9895e94a 100644
--- a/apps/web/components/ui/select.tsx
+++ b/apps/web/components/ui/select.tsx
@@ -1,11 +1,10 @@
"use client";
import * as React from "react";
+import { cn } from "@/lib/utils";
import * as SelectPrimitive from "@radix-ui/react-select";
import { Check, ChevronDown, ChevronUp } from "lucide-react";
-import { cn } from "@/lib/utils";
-
const Select = SelectPrimitive.Root;
const SelectGroup = SelectPrimitive.Group;
@@ -19,7 +18,7 @@ const SelectTrigger = React.forwardRef<
<SelectPrimitive.Trigger
ref={ref}
className={cn(
- "border-input bg-background ring-offset-background placeholder:text-muted-foreground focus:ring-ring flex h-10 w-full items-center justify-between rounded-md border px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
+ "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
className,
)}
{...props}
@@ -75,7 +74,7 @@ const SelectContent = React.forwardRef<
<SelectPrimitive.Content
ref={ref}
className={cn(
- "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border shadow-md",
+ "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
position === "popper" &&
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className,
@@ -118,7 +117,7 @@ const SelectItem = React.forwardRef<
<SelectPrimitive.Item
ref={ref}
className={cn(
- "focus:bg-accent focus:text-accent-foreground relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className,
)}
{...props}
@@ -140,7 +139,7 @@ const SelectSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
<SelectPrimitive.Separator
ref={ref}
- className={cn("bg-muted -mx-1 my-1 h-px", className)}
+ className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props}
/>
));
diff --git a/apps/web/components/ui/separator.tsx b/apps/web/components/ui/separator.tsx
index 3b9f2b84..09303128 100644
--- a/apps/web/components/ui/separator.tsx
+++ b/apps/web/components/ui/separator.tsx
@@ -1,9 +1,8 @@
"use client";
import * as React from "react";
-import * as SeparatorPrimitive from "@radix-ui/react-separator";
-
import { cn } from "@/lib/utils";
+import * as SeparatorPrimitive from "@radix-ui/react-separator";
const Separator = React.forwardRef<
React.ElementRef<typeof SeparatorPrimitive.Root>,
@@ -18,7 +17,7 @@ const Separator = React.forwardRef<
decorative={decorative}
orientation={orientation}
className={cn(
- "bg-border shrink-0",
+ "shrink-0 bg-border",
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
className,
)}
diff --git a/apps/web/components/ui/skeleton.tsx b/apps/web/components/ui/skeleton.tsx
index 5fab2023..2cdf440d 100644
--- a/apps/web/components/ui/skeleton.tsx
+++ b/apps/web/components/ui/skeleton.tsx
@@ -6,7 +6,7 @@ function Skeleton({
}: React.HTMLAttributes<HTMLDivElement>) {
return (
<div
- className={cn("bg-muted animate-pulse rounded-md", className)}
+ className={cn("animate-pulse rounded-md bg-muted", className)}
{...props}
/>
);
diff --git a/apps/web/components/ui/table.tsx b/apps/web/components/ui/table.tsx
index 0fa9288e..95b43b8c 100644
--- a/apps/web/components/ui/table.tsx
+++ b/apps/web/components/ui/table.tsx
@@ -1,5 +1,4 @@
import * as React from "react";
-
import { cn } from "@/lib/utils";
const Table = React.forwardRef<
@@ -43,7 +42,7 @@ const TableFooter = React.forwardRef<
<tfoot
ref={ref}
className={cn(
- "bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
+ "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
className,
)}
{...props}
@@ -58,7 +57,7 @@ const TableRow = React.forwardRef<
<tr
ref={ref}
className={cn(
- "hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
+ "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
className,
)}
{...props}
@@ -73,7 +72,7 @@ const TableHead = React.forwardRef<
<th
ref={ref}
className={cn(
- "text-muted-foreground h-12 px-4 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0",
+ "h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
className,
)}
{...props}
@@ -99,7 +98,7 @@ const TableCaption = React.forwardRef<
>(({ className, ...props }, ref) => (
<caption
ref={ref}
- className={cn("text-muted-foreground mt-4 text-sm", className)}
+ className={cn("mt-4 text-sm text-muted-foreground", className)}
{...props}
/>
));
diff --git a/apps/web/components/ui/tabs.tsx b/apps/web/components/ui/tabs.tsx
index 990017db..4c1b0ab1 100644
--- a/apps/web/components/ui/tabs.tsx
+++ b/apps/web/components/ui/tabs.tsx
@@ -1,9 +1,8 @@
"use client";
import * as React from "react";
-import * as TabsPrimitive from "@radix-ui/react-tabs";
-
import { cn } from "@/lib/utils";
+import * as TabsPrimitive from "@radix-ui/react-tabs";
const Tabs = TabsPrimitive.Root;
@@ -14,7 +13,7 @@ const TabsList = React.forwardRef<
<TabsPrimitive.List
ref={ref}
className={cn(
- "bg-muted text-muted-foreground inline-flex h-10 items-center justify-center rounded-md p-1",
+ "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
className,
)}
{...props}
@@ -29,7 +28,7 @@ const TabsTrigger = React.forwardRef<
<TabsPrimitive.Trigger
ref={ref}
className={cn(
- "ring-offset-background focus-visible:ring-ring data-[state=active]:bg-background data-[state=active]:text-foreground inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm",
+ "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
className,
)}
{...props}
@@ -44,7 +43,7 @@ const TabsContent = React.forwardRef<
<TabsPrimitive.Content
ref={ref}
className={cn(
- "ring-offset-background focus-visible:ring-ring mt-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
+ "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
className,
)}
{...props}
diff --git a/apps/web/components/ui/textarea.tsx b/apps/web/components/ui/textarea.tsx
index a0de3371..98d704ae 100644
--- a/apps/web/components/ui/textarea.tsx
+++ b/apps/web/components/ui/textarea.tsx
@@ -1,16 +1,14 @@
import * as React from "react";
-
import { cn } from "@/lib/utils";
-export interface TextareaProps
- extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
+export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ className, ...props }, ref) => {
return (
<textarea
className={cn(
- "border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex min-h-[80px] w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
+ "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
ref={ref}
diff --git a/apps/web/components/ui/toast.tsx b/apps/web/components/ui/toast.tsx
index 0d162dca..16c2f76f 100644
--- a/apps/web/components/ui/toast.tsx
+++ b/apps/web/components/ui/toast.tsx
@@ -1,10 +1,10 @@
+import type { VariantProps } from "class-variance-authority";
import * as React from "react";
+import { cn } from "@/lib/utils";
import * as ToastPrimitives from "@radix-ui/react-toast";
-import { cva, type VariantProps } from "class-variance-authority";
+import { cva } from "class-variance-authority";
import { X } from "lucide-react";
-import { cn } from "@/lib/utils";
-
const ToastProvider = ToastPrimitives.Provider;
const ToastViewport = React.forwardRef<
@@ -23,13 +23,13 @@ const ToastViewport = React.forwardRef<
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
const toastVariants = cva(
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none",
+ "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
{
variants: {
variant: {
- default: "bg-background text-foreground border",
+ default: "border bg-background text-foreground",
destructive:
- "destructive border-destructive bg-destructive text-destructive-foreground group",
+ "destructive group border-destructive bg-destructive text-destructive-foreground",
},
},
defaultVariants: {
@@ -60,7 +60,7 @@ const ToastAction = React.forwardRef<
<ToastPrimitives.Action
ref={ref}
className={cn(
- "ring-offset-background hover:bg-secondary focus:ring-ring group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
+ "inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",
className,
)}
{...props}
@@ -75,7 +75,7 @@ const ToastClose = React.forwardRef<
<ToastPrimitives.Close
ref={ref}
className={cn(
- "text-foreground/50 hover:text-foreground absolute right-2 top-2 rounded-md p-1 opacity-0 transition-opacity focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
+ "absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
className,
)}
toast-close=""
diff --git a/apps/web/components/ui/use-toast.ts b/apps/web/components/ui/use-toast.ts
index 5491e140..5ec5aa36 100644
--- a/apps/web/components/ui/use-toast.ts
+++ b/apps/web/components/ui/use-toast.ts
@@ -1,7 +1,6 @@
// Inspired by react-hot-toast library
-import * as React from "react";
-
import type { ToastActionElement, ToastProps } from "@/components/ui/toast";
+import * as React from "react";
const TOAST_LIMIT = 1;
const TOAST_REMOVE_DELAY = 1000000;
@@ -124,7 +123,7 @@ export const reducer = (state: State, action: Action): State => {
}
};
-const listeners: Array<(_state: State) => void> = [];
+const listeners: ((_state: State) => void)[] = [];
let memoryState: State = { toasts: [] };
diff --git a/apps/web/lib/bookmarkUtils.tsx b/apps/web/lib/bookmarkUtils.tsx
index a2828c29..fbb7c7df 100644
--- a/apps/web/lib/bookmarkUtils.tsx
+++ b/apps/web/lib/bookmarkUtils.tsx
@@ -1,4 +1,4 @@
-import { ZBookmark } from "@hoarder/trpc/types/bookmarks";
+import type { ZBookmark } from "@hoarder/trpc/types/bookmarks";
const MAX_LOADING_MSEC = 30 * 1000;
diff --git a/apps/web/lib/hooks/bookmark-search.ts b/apps/web/lib/hooks/bookmark-search.ts
index 738e1bd8..1971e79e 100644
--- a/apps/web/lib/hooks/bookmark-search.ts
+++ b/apps/web/lib/hooks/bookmark-search.ts
@@ -1,11 +1,11 @@
import { useEffect, useState } from "react";
-import { api } from "@/lib/trpc";
import { useRouter, useSearchParams } from "next/navigation";
+import { api } from "@/lib/trpc";
import { keepPreviousData } from "@tanstack/react-query";
function useSearchQuery() {
const searchParams = useSearchParams();
- const searchQuery = searchParams.get("q") || "";
+ const searchQuery = searchParams.get("q") ?? "";
return { searchQuery };
}
diff --git a/apps/web/lib/providers.tsx b/apps/web/lib/providers.tsx
index 5c4649b5..db51c361 100644
--- a/apps/web/lib/providers.tsx
+++ b/apps/web/lib/providers.tsx
@@ -1,13 +1,13 @@
"use client";
-import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import type { Session } from "next-auth";
import React, { useState } from "react";
-import { api } from "./trpc";
-import { loggerLink } from "@trpc/client";
-import { httpBatchLink } from "@trpc/client";
-import superjson from "superjson";
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { httpBatchLink, loggerLink } from "@trpc/client";
import { SessionProvider } from "next-auth/react";
-import { Session } from "next-auth";
+import superjson from "superjson";
+
+import { api } from "./trpc";
function makeQueryClient() {
return new QueryClient({
diff --git a/apps/web/lib/trpc.tsx b/apps/web/lib/trpc.tsx
index 79a2a9fe..99fdd8b5 100644
--- a/apps/web/lib/trpc.tsx
+++ b/apps/web/lib/trpc.tsx
@@ -1,5 +1,7 @@
"use client";
-import type { AppRouter } from "@hoarder/trpc/routers/_app";
+
import { createTRPCReact } from "@trpc/react-query";
+import type { AppRouter } from "@hoarder/trpc/routers/_app";
+
export const api = createTRPCReact<AppRouter>();
diff --git a/apps/web/lib/utils.ts b/apps/web/lib/utils.ts
index 365058ce..88283f01 100644
--- a/apps/web/lib/utils.ts
+++ b/apps/web/lib/utils.ts
@@ -1,4 +1,5 @@
-import { type ClassValue, clsx } from "clsx";
+import type { ClassValue } from "clsx";
+import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs
index fa0757dd..041ab6b3 100644
--- a/apps/web/next.config.mjs
+++ b/apps/web/next.config.mjs
@@ -39,11 +39,7 @@ const nextConfig = withPWA({
];
},
- transpilePackages: [
- "@hoarder/shared",
- "@hoarder/db",
- "@hoarder/trpc",
- ],
+ transpilePackages: ["@hoarder/shared", "@hoarder/db", "@hoarder/trpc"],
/** We already do linting and typechecking as separate tasks in CI */
eslint: { ignoreDuringBuilds: true },
diff --git a/apps/web/server/api/client.ts b/apps/web/server/api/client.ts
index 88ea7a0e..8b414d39 100644
--- a/apps/web/server/api/client.ts
+++ b/apps/web/server/api/client.ts
@@ -1,7 +1,8 @@
-import { appRouter } from "@hoarder/trpc/routers/_app";
import { getServerAuthSession } from "@/server/auth";
-import { Context, createCallerFactory } from "@hoarder/trpc";
+
import { db } from "@hoarder/db";
+import { Context, createCallerFactory } from "@hoarder/trpc";
+import { appRouter } from "@hoarder/trpc/routers/_app";
export const createContext = async (database?: typeof db): Promise<Context> => {
const session = await getServerAuthSession();
diff --git a/apps/web/server/auth.ts b/apps/web/server/auth.ts
index 950443b9..767bc7e8 100644
--- a/apps/web/server/auth.ts
+++ b/apps/web/server/auth.ts
@@ -1,15 +1,18 @@
-import NextAuth, { NextAuthOptions, getServerSession } from "next-auth";
import type { Adapter } from "next-auth/adapters";
+import { DrizzleAdapter } from "@auth/drizzle-adapter";
+import NextAuth, {
+ DefaultSession,
+ getServerSession,
+ NextAuthOptions,
+} from "next-auth";
import AuthentikProvider from "next-auth/providers/authentik";
-import serverConfig from "@hoarder/shared/config";
-import { validatePassword } from "@hoarder/trpc/auth";
-import { db } from "@hoarder/db";
-import { DefaultSession } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
-import { DrizzleAdapter } from "@auth/drizzle-adapter";
-
import { Provider } from "next-auth/providers/index";
+import { db } from "@hoarder/db";
+import serverConfig from "@hoarder/shared/config";
+import { validatePassword } from "@hoarder/trpc/auth";
+
declare module "next-auth/jwt" {
export interface JWT {
user: {
diff --git a/apps/web/vitest.config.ts b/apps/web/vitest.config.ts
index c3d02f71..41fd70c4 100644
--- a/apps/web/vitest.config.ts
+++ b/apps/web/vitest.config.ts
@@ -1,7 +1,7 @@
/// <reference types="vitest" />
-import { defineConfig } from "vitest/config";
import tsconfigPaths from "vite-tsconfig-paths";
+import { defineConfig } from "vitest/config";
// https://vitejs.dev/config/
export default defineConfig({
diff --git a/package.json b/package.json
index 74028b20..31a04b04 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,6 @@
"dev": "turbo dev --parallel",
"clean": "git clean -xdf node_modules",
"clean:workspaces": "turbo clean",
- "format:check": "prettier 'packages/**/*.{js,ts,tsx,mjs,cjs}' --check",
"db:migrate": "pnpm --filter @hoarder/db run migrate",
"db:studio": "pnpm --filter @hoarder/db studio",
"workers": "pnpm --filter @hoarder/workers run start",
diff --git a/packages/shared/index.ts b/packages/shared/index.ts
index 8b93520f..e449443d 100644
--- a/packages/shared/index.ts
+++ b/packages/shared/index.ts
@@ -1 +1 @@
-export * as Queues from "./queues.ts";
+export * as Queues from "./queues";
diff --git a/packages/trpc/index.ts b/packages/trpc/index.ts
index bcfa7211..51c713c0 100644
--- a/packages/trpc/index.ts
+++ b/packages/trpc/index.ts
@@ -2,6 +2,7 @@ import { db } from "@hoarder/db";
import serverConfig from "@hoarder/shared/config";
import { TRPCError, initTRPC } from "@trpc/server";
import superjson from "superjson";
+import { ZodError } from "zod";
type User = {
id: string;
@@ -21,6 +22,19 @@ export type Context = {
// is common in i18n libraries.
const t = initTRPC.context<Context>().create({
transformer: superjson,
+ errorFormatter(opts) {
+ const { shape, error } = opts;
+ return {
+ ...shape,
+ data: {
+ ...shape.data,
+ zodError:
+ error.code === 'BAD_REQUEST' && error.cause instanceof ZodError
+ ? error.cause.flatten()
+ : null,
+ },
+ };
+ },
});
export const createCallerFactory = t.createCallerFactory;
// Base router and procedure helpers
diff --git a/tooling/eslint/base.js b/tooling/eslint/base.js
index d1f6296c..2bc62548 100644
--- a/tooling/eslint/base.js
+++ b/tooling/eslint/base.js
@@ -28,6 +28,8 @@ const config = {
{ checksVoidReturn: { attributes: false } },
],
"import/consistent-type-specifier-style": ["error", "prefer-top-level"],
+ "@typescript-eslint/no-floating-promises": "off",
+ "@typescript-eslint/unbound-method": "off",
},
ignorePatterns: [
"**/*.config.js",
diff --git a/tooling/eslint/package.json b/tooling/eslint/package.json
index 5329f6d2..6b156d5d 100644
--- a/tooling/eslint/package.json
+++ b/tooling/eslint/package.json
@@ -39,4 +39,4 @@
]
},
"prettier": "@hoarder/prettier-config"
-} \ No newline at end of file
+}
diff --git a/tooling/eslint/react.js b/tooling/eslint/react.js
index 618e1816..38b735b9 100644
--- a/tooling/eslint/react.js
+++ b/tooling/eslint/react.js
@@ -7,6 +7,9 @@ const config = {
],
rules: {
"react/prop-types": "off",
+ "jsx-a11y/no-autofocus": "off",
+ "jsx-a11y/label-has-associated-control": "off",
+ "react-hooks/exhaustive-deps": "off",
},
globals: {
React: "writable",
diff --git a/turbo.json b/turbo.json
index 92c6720a..8ecad061 100644
--- a/turbo.json
+++ b/turbo.json
@@ -38,12 +38,5 @@
"//#clean": {
"cache": false
}
- },
- "globalEnv": [
- "DATABASE_URL",
- "AUTH_DISCORD_ID",
- "AUTH_DISCORD_SECRET",
- "AUTH_REDIRECT_PROXY_URL",
- "AUTH_SECRET"
- ]
+ }
}