From 13913715a2f73a62e86b30d563baffcfffb4c566 Mon Sep 17 00:00:00 2001 From: vwh Date: Wed, 6 Nov 2024 23:07:16 +0300 Subject: [PATCH] refactor: yet another refactor man, my code sucks fr --- src/App.tsx | 19 +-- src/components/database/page-select.tsx | 8 +- src/components/database/query-textarea.tsx | 1 - src/components/landing/dropzone.tsx | 9 +- src/components/landing/features.tsx | 12 +- src/components/landing/footer.tsx | 2 + src/components/landing/url-fetch.tsx | 5 +- src/components/settings/export-buttons.tsx | 14 +-- src/components/settings/settings-drawer.tsx | 22 ++-- src/components/settings/settings-sections.tsx | 112 +++++++++--------- src/components/settings/theme-mode-toggle.tsx | 3 + src/components/stats-message.tsx | 4 + src/hooks/usePagination.ts | 4 +- 13 files changed, 111 insertions(+), 104 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index fc0e09f..5a8e151 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,8 +1,6 @@ import { memo } from "react"; import useSQLiteStore from "@/store/useSQLiteStore"; -import type { Database } from "sql.js"; - import DBTable from "@/components/database/upper-section"; import UploadFile from "@/components/landing/dropzone"; import Hero from "@/components/landing/hero"; @@ -10,30 +8,25 @@ import Features from "@/components/landing/features"; import UrlFetch from "@/components/landing/url-fetch"; import Footer from "@/components/landing/footer"; -interface DBTableProps { - isDatabaseLoaded: Database; -} - -const MemoizedDBTable = memo(DBTable); +const MemoizedDBTable = memo(DBTable); const MemoizedUploadFile = memo(UploadFile); const MemoizedUrlFetch = memo(UrlFetch); export default function App() { - const { db: isDatabaseLoaded, expandPage } = useSQLiteStore(); + const { db, expandPage } = useSQLiteStore(); return (
- {!isDatabaseLoaded && ( + {!db ? ( <>
- )} - {isDatabaseLoaded && ( - + ) : ( + )}
); diff --git a/src/components/database/page-select.tsx b/src/components/database/page-select.tsx index 2ed8697..a16742e 100644 --- a/src/components/database/page-select.tsx +++ b/src/components/database/page-select.tsx @@ -35,15 +35,11 @@ export default function PageSelect({ const canGoPrev = currentPage > 1; const nextPage = useCallback(() => { - if (canGoNext) { - setPage((prevPage) => prevPage + rowsPerPage); - } + if (canGoNext) setPage((prevPage) => prevPage + rowsPerPage); }, [canGoNext, rowsPerPage, setPage]); const prevPage = useCallback(() => { - if (canGoPrev) { - setPage((prevPage) => prevPage - rowsPerPage); - } + if (canGoPrev) setPage((prevPage) => prevPage - rowsPerPage); }, [canGoPrev, rowsPerPage, setPage]); return ( diff --git a/src/components/database/query-textarea.tsx b/src/components/database/query-textarea.tsx index 4dd1287..3179634 100644 --- a/src/components/database/query-textarea.tsx +++ b/src/components/database/query-textarea.tsx @@ -3,7 +3,6 @@ import useSQLiteStore from "@/store/useSQLiteStore"; import useTheme from "@/hooks/useTheme"; import { sql, SQLite } from "@codemirror/lang-sql"; - import CodeMirror from "@uiw/react-codemirror"; import { autocompletion, diff --git a/src/components/landing/dropzone.tsx b/src/components/landing/dropzone.tsx index 129db5f..6c435cf 100644 --- a/src/components/landing/dropzone.tsx +++ b/src/components/landing/dropzone.tsx @@ -27,7 +27,6 @@ const ACCEPTED_TYPES = { function UploadFile() { const { loadDatabaseBytes, setDatabaseData } = useSQLiteStore(); - const [errors, setErrors] = useState([]); const onDrop = useCallback( @@ -36,19 +35,22 @@ function UploadFile() { const rejectionErrors = fileRejections.flatMap( (rejection) => rejection.errors ); + setErrors(rejectionErrors); return; } + if (acceptedFiles.length > 0) { try { const file = acceptedFiles[0]; const bytes = new Uint8Array(await file.arrayBuffer()); + setDatabaseData({ name: file.name, size: file.size }); await loadDatabaseBytes(bytes); } catch (error) { - if (error instanceof Error) { + if (error instanceof Error) return toast(error.message, { position: "bottom-right" }); - } + return toast("Failed to load database", { position: "bottom-right" }); @@ -111,6 +113,7 @@ const FileStats: React.FC<{ errors?: FileError[] }> = memo(({ errors }) => { } } }, [errors]); + return null; }); diff --git a/src/components/landing/features.tsx b/src/components/landing/features.tsx index 0fa30c7..d316e83 100644 --- a/src/components/landing/features.tsx +++ b/src/components/landing/features.tsx @@ -7,12 +7,6 @@ import { AppWindowIcon } from "lucide-react"; -interface FeatureProps { - title: string; - description: string; - icon: React.ElementType; -} - export default function Features() { return ( <> @@ -59,6 +53,12 @@ export default function Features() { ); } +interface FeatureProps { + title: string; + description: string; + icon: React.ElementType; +} + function Feature({ icon: Icon, title, description }: FeatureProps) { return (
diff --git a/src/components/landing/footer.tsx b/src/components/landing/footer.tsx index 07d0d0b..504f905 100644 --- a/src/components/landing/footer.tsx +++ b/src/components/landing/footer.tsx @@ -1,5 +1,7 @@ import { memo } from "react"; + import ThemeModeToggle from "@/components/settings/theme-mode-toggle"; + import { GithubIcon } from "lucide-react"; function Footer() { diff --git a/src/components/landing/url-fetch.tsx b/src/components/landing/url-fetch.tsx index 0645b9f..3d6264b 100644 --- a/src/components/landing/url-fetch.tsx +++ b/src/components/landing/url-fetch.tsx @@ -29,6 +29,7 @@ export default function UrlFetch() { setFetchError("Invalid URL"); return; } + try { setIsFetching(true); const fetchUrl = useProxy @@ -36,9 +37,7 @@ export default function UrlFetch() { : url; const response = await fetch(fetchUrl); - if (!response.ok) { - throw new Error("URL not found or invalid"); - } + if (!response.ok) throw new Error("URL not found or invalid"); const blob = await response.blob(); const file = new File([blob], "database.sqlite"); diff --git a/src/components/settings/export-buttons.tsx b/src/components/settings/export-buttons.tsx index e89e0a1..df35fdf 100644 --- a/src/components/settings/export-buttons.tsx +++ b/src/components/settings/export-buttons.tsx @@ -37,6 +37,7 @@ export default function ExportButtons() { label="Export as SQLite" title="Download database as SQLite" /> + { try { @@ -47,6 +48,7 @@ export default function ExportButtons() { }} label="Export selected table as CSV" /> + { try { @@ -57,6 +59,7 @@ export default function ExportButtons() { }} label="Export all tables as CSV" /> + { try { @@ -87,17 +90,14 @@ export default function ExportButtons() { ); } -function ExportButton({ - onClick, - label, - className, - title -}: { +interface ExportButtonProps { onClick: () => void; label: string; className?: string; title?: string; -}) { +} + +function ExportButton({ onClick, label, className, title }: ExportButtonProps) { return (
); -}; +} type DateFormatSectionProps = { dateFormatValue: string; onDateFormatChange: (value: string) => void; }; -export const DateFormatSection: React.FC = ({ +export function DateFormatSection({ dateFormatValue, onDateFormatChange -}) => ( -
-
- -

Date Format

-
-
- - +}: DateFormatSectionProps) { + return ( +
+
+ +

Date Format

+
+
+ + +
-
-); + ); +} type ThemeColorSectionProps = { themeColor: string; @@ -94,30 +98,32 @@ type ThemeColorSectionProps = { themeColors: string[]; }; -export const ThemeColorSection: React.FC = ({ +export function ThemeColorSection({ themeColor, onThemeColorChange, themeColors -}) => ( -
-
- -

Theme Color

+}: ThemeColorSectionProps) { + return ( +
+
+ +

Theme Color

+
+ +
- - -
-); + ); +} diff --git a/src/components/settings/theme-mode-toggle.tsx b/src/components/settings/theme-mode-toggle.tsx index addc1b3..788fdfc 100644 --- a/src/components/settings/theme-mode-toggle.tsx +++ b/src/components/settings/theme-mode-toggle.tsx @@ -14,6 +14,7 @@ function ThemeModeToggle() { const prefersDark = window.matchMedia( "(prefers-color-scheme: dark)" ).matches; + return savedTheme || (prefersDark ? "dark" : "light"); }); @@ -22,9 +23,11 @@ function ThemeModeToggle() { document.body.classList.remove("light", "dark"); document.body.classList.add(newTheme); + localStorage.setItem(THEME_KEY, newTheme); document.body.classList.add(ANIMATION_CLASS); + setTimeout(() => { document.body.classList.remove(ANIMATION_CLASS); }, 500); diff --git a/src/components/stats-message.tsx b/src/components/stats-message.tsx index 4f073f7..1dbd8b5 100644 --- a/src/components/stats-message.tsx +++ b/src/components/stats-message.tsx @@ -30,6 +30,7 @@ export default function StatusMessage({ icon = ; typeClasses = "bg-red-100 text-red-800 border-l-4 border-red-500"; break; + case "loading": { icon = ( @@ -37,15 +38,18 @@ export default function StatusMessage({ typeClasses = "bg-blue-100 text-blue-800 border-l-4 border-blue-500"; break; } + case "success": icon = ; typeClasses = "bg-green-100 text-green-800 border-l-4 border-green-500"; break; + case "info": icon = ; typeClasses = "bg-yellow-100 text-yellow-800 border-l-4 border-yellow-500"; break; + default: icon = null; typeClasses = ""; diff --git a/src/hooks/usePagination.ts b/src/hooks/usePagination.ts index b79d792..7ec36f6 100644 --- a/src/hooks/usePagination.ts +++ b/src/hooks/usePagination.ts @@ -11,9 +11,7 @@ export function usePagination(rowPerPageOrAuto: "auto" | number) { }, [setIsCustomQuery]); const rowsPerPage = useMemo(() => { - if (rowPerPageOrAuto !== "auto") { - return rowPerPageOrAuto; - } + if (rowPerPageOrAuto !== "auto") return rowPerPageOrAuto; const screenHeight = window.innerHeight;