diff --git a/package-lock.json b/package-lock.json index 1a7b235..80cee3d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,10 +8,13 @@ "name": "hardware-monitor", "version": "0.0.1", "dependencies": { + "@hookform/resolvers": "^3.9.0", "@phosphor-icons/react": "^2.1.7", + "@radix-ui/react-checkbox": "^1.1.1", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-select": "^2.1.1", + "@radix-ui/react-slider": "^1.2.1", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-switch": "^1.1.0", "@tauri-apps/api": "^1", @@ -23,9 +26,11 @@ "react": "^18.3.1", "react-chartjs-2": "^5.2.0", "react-dom": "^18.3.1", + "react-hook-form": "^7.53.0", "tailwind-merge": "^2.5.2", "tailwind-variants": "^0.2.1", - "tailwindcss-animate": "^1.0.7" + "tailwindcss-animate": "^1.0.7", + "zod": "^3.23.8" }, "devDependencies": { "@biomejs/biome": "1.9.2", @@ -963,6 +968,15 @@ "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==", "license": "MIT" }, + "node_modules/@hookform/resolvers": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.9.0.tgz", + "integrity": "sha512-bU0Gr4EepJ/EQsH/IwEzYLsT/PEj5C0ynLQ4m+GSHS+xKH4TfSelhluTgOaoc4kA5s7eCsQbM4wvZLzELmWzUg==", + "license": "MIT", + "peerDependencies": { + "react-hook-form": "^7.0.0" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1127,6 +1141,36 @@ } } }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.1.tgz", + "integrity": "sha512-0i/EKJ222Afa1FE0C6pNJxDq1itzcl3HChE9DwskA4th4KRse8ojx8a1nVcOjwJdbpDLcz7uol77yYnQNMHdKw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-use-size": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-collection": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", @@ -1488,6 +1532,54 @@ } } }, + "node_modules/@radix-ui/react-slider": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.2.1.tgz", + "integrity": "sha512-bEzQoDW0XP+h/oGbutF5VMWJPAl/UU8IJjr7h02SOHDIIIxq+cep8nItVNoBV+OMmahCdqdF38FTpmXoqQUGvw==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.0", + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-collection": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-use-size": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", @@ -3736,6 +3828,22 @@ "react": "^18.3.1" } }, + "node_modules/react-hook-form": { + "version": "7.53.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.53.0.tgz", + "integrity": "sha512-M1n3HhqCww6S2hxLxciEXy2oISPnAzxY7gvwVPrtlczTM/1dDadXgUxDpHMrMTblDOcm/AXtXxHwZ3jpg1mqKQ==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, "node_modules/react-refresh": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", @@ -4738,6 +4846,15 @@ "engines": { "node": ">= 14" } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index 6445785..28ee6b5 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "test": "vitest", "tauri": "tauri", "lint": "biome lint ./src && biome check ./src && biome format --write ./src", - "format": "biome format --write ./src && biome check ./src", + "format": "biome format --write ./src && biome check ./src --write", "lint:ci": "biome ci ./src" }, "devDependencies": { @@ -28,10 +28,13 @@ "vitest": "^2.0.5" }, "dependencies": { + "@hookform/resolvers": "^3.9.0", "@phosphor-icons/react": "^2.1.7", + "@radix-ui/react-checkbox": "^1.1.1", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-select": "^2.1.1", + "@radix-ui/react-slider": "^1.2.1", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-switch": "^1.1.0", "@tauri-apps/api": "^1", @@ -43,8 +46,10 @@ "react": "^18.3.1", "react-chartjs-2": "^5.2.0", "react-dom": "^18.3.1", + "react-hook-form": "^7.53.0", "tailwind-merge": "^2.5.2", "tailwind-variants": "^0.2.1", - "tailwindcss-animate": "^1.0.7" + "tailwindcss-animate": "^1.0.7", + "zod": "^3.23.8" } } diff --git a/src-tauri/src/commands/config.rs b/src-tauri/src/commands/config.rs index 3e8c6d3..b29f574 100644 --- a/src-tauri/src/commands/config.rs +++ b/src-tauri/src/commands/config.rs @@ -19,6 +19,7 @@ pub struct Settings { language: String, theme: String, display_targets: Vec, + graphSize: String, } impl Default for Settings { @@ -31,6 +32,7 @@ impl Default for Settings { hardware::HardwareType::Memory, hardware::HardwareType::GPU, ], + graphSize: "xl".to_string(), } } } @@ -133,6 +135,11 @@ impl Settings { self.display_targets = new_targets; self.write_file() } + + pub fn set_graph_size(&mut self, new_size: String) -> Result<(), String> { + self.graphSize = new_size; + self.write_file() + } } #[derive(Debug)] @@ -179,7 +186,6 @@ pub mod commands { } #[tauri::command] - pub async fn set_language( window: Window, state: tauri::State<'_, AppState>, @@ -225,4 +231,19 @@ pub mod commands { } Ok(()) } + + #[tauri::command] + pub async fn set_graph_size( + window: Window, + state: tauri::State<'_, AppState>, + new_size: String, + ) -> Result<(), String> { + let mut settings = state.settings.lock().unwrap(); + + if let Err(e) = settings.set_graph_size(new_size) { + emit_error(&window)?; + return Err(e); + } + Ok(()) + } } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index c375f2c..c8b1b13 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -66,10 +66,11 @@ fn main() { hardware::get_cpu_usage_history, hardware::get_memory_usage_history, hardware::get_gpu_usage_history, + config::commands::get_settings, config::commands::set_language, config::commands::set_theme, config::commands::set_display_targets, - config::commands::get_settings + config::commands::set_graph_size, ]) .on_menu_event(|event| { window_menu_service::handle_menu_event(event); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 601f116..838c819 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "hardware-monitor", - "version": "0.1.0" + "version": "0.1.1" }, "tauri": { "allowlist": { diff --git a/src/App.tsx b/src/App.tsx index 1eb0bdd..869a938 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,11 +7,12 @@ import { useErrorModalListener, useSettingsModalListener, } from "@/hooks/useTauriEventListener"; -import SettingsSheet from "@/template/SettingsSheet"; import { useAtom } from "jotai"; import { selectedMenuAtom } from "./atom/ui"; import { useSettingsAtom } from "./atom/useSettingsAtom"; import { useDarkMode } from "./hooks/useDarkMode"; +import ScreenTemplate from "./template/ScreenTemplate"; +import Settings from "./template/Settings"; import SideMenu from "./template/SideMenu"; import type { SelectedMenuType } from "./types/ui"; @@ -35,16 +36,23 @@ const Page = () => { }, [settings?.theme, toggle]); const displayTargets: Record = { - dashboard: , + dashboard: ( + + + + ), usage: , - settings:
TODO
, + settings: ( + + + + ), }; return (
{displayTargets[selectedMenu]} -
); }; diff --git a/src/atom/useSettingsAtom.ts b/src/atom/useSettingsAtom.ts index f8f71f7..5f3a1c9 100644 --- a/src/atom/useSettingsAtom.ts +++ b/src/atom/useSettingsAtom.ts @@ -1,6 +1,8 @@ import { getSettings, setDisplayTargets, + setGraphSize, + setLanguage, setTheme, } from "@/services/settingService"; import type { ChartDataType } from "@/types/hardwareDataType"; @@ -11,9 +13,19 @@ const settingsAtom = atom({ language: "en", theme: "light", display_targets: [], + graphSize: "xl", }); export const useSettingsAtom = () => { + const mapSettingUpdater: { + [K in keyof Settings]: (value: Settings[K]) => Promise; + } = { + theme: setTheme, + display_targets: setDisplayTargets, + graphSize: setGraphSize, + language: setLanguage, + }; + const [settings, setSettings] = useAtom(settingsAtom); useEffect(() => { @@ -24,6 +36,18 @@ export const useSettingsAtom = () => { loadSettings(); }, [setSettings]); + const updateSettingAtom = async ( + key: K, + value: Settings[K], + ) => { + try { + await mapSettingUpdater[key](value); + setSettings((prev) => ({ ...prev, [key]: value })); + } catch (e) { + console.error(e); + } + }; + const toggleDisplayTarget = async (target: ChartDataType) => { const newTargets = settings.display_targets.includes(target) ? settings.display_targets.filter((t) => t !== target) @@ -38,14 +62,9 @@ export const useSettingsAtom = () => { } }; - const toggleTheme = async (theme: "light" | "dark") => { - try { - await setTheme(theme); - setSettings((prev) => ({ ...prev, theme })); - } catch (e) { - console.error(e); - } + return { + settings, + toggleDisplayTarget, + updateSettingAtom, }; - - return { settings, toggleDisplayTarget, toggleTheme }; }; diff --git a/src/components/charts/LineChart.tsx b/src/components/charts/LineChart.tsx index 5ed3acf..b8eaeda 100644 --- a/src/components/charts/LineChart.tsx +++ b/src/components/charts/LineChart.tsx @@ -1,3 +1,4 @@ +import { useSettingsAtom } from "@/atom/useSettingsAtom"; import type { ChartDataType } from "@/types/hardwareDataType"; import { Cpu, GraphicsCard, Memory } from "@phosphor-icons/react"; import { @@ -15,6 +16,7 @@ import { import type { Chart, ChartData } from "chart.js"; import { useRef } from "react"; import { Line } from "react-chartjs-2"; +import { tv } from "tailwind-variants"; import CustomLegend, { type LegendItem } from "./CustomLegend"; ChartJS.register( @@ -37,6 +39,8 @@ const LineChart = ({ chartData: number[]; dataType: ChartDataType; }) => { + const { settings } = useSettingsAtom(); + const chartRef = useRef>(null); const options: ChartOptions<"line"> = { @@ -133,8 +137,24 @@ const LineChart = ({ }, }; + const graphVariants = tv({ + base: "mt-5 mx-auto", + variants: { + size: { + sm: "max-w-screen-sm", + md: "max-w-screen-md", + lg: "max-w-screen-lg", + xl: "max-w-screen-xl", + "2xl": "max-w-screen-2xl", + }, + }, + defaultVariants: { + size: "xl", + }, + }); + return ( -
+
{ try { const processesData = await getProcesses(); - console.log(processesData); setAtom(processesData); } catch (error) { console.error("Failed to fetch processes:", error); diff --git a/src/components/ui/select.tsx b/src/components/ui/select.tsx new file mode 100644 index 0000000..eed05da --- /dev/null +++ b/src/components/ui/select.tsx @@ -0,0 +1,161 @@ +import * as SelectPrimitive from "@radix-ui/react-select"; +import { Check, ChevronDown, ChevronUp } from "lucide-react"; +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const Select = SelectPrimitive.Root; + +const SelectGroup = SelectPrimitive.Group; + +const SelectValue = SelectPrimitive.Value; + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + span]:line-clamp-1 dark:border-neutral-800 dark:bg-neutral-950 dark:ring-offset-neutral-950 dark:placeholder:text-neutral-400 dark:focus:ring-neutral-300", + className, + )} + {...props} + > + {children} + + + + +)); +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; + +const SelectScrollUpButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; + +const SelectScrollDownButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollDownButton.displayName = + SelectPrimitive.ScrollDownButton.displayName; + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = "popper", ...props }, ref) => ( + + + + + {children} + + + + +)); +SelectContent.displayName = SelectPrimitive.Content.displayName; + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectLabel.displayName = SelectPrimitive.Label.displayName; + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + + {children} + +)); +SelectItem.displayName = SelectPrimitive.Item.displayName; + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectSeparator.displayName = SelectPrimitive.Separator.displayName; + +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, + SelectScrollUpButton, + SelectScrollDownButton, +}; diff --git a/src/components/ui/sheet.tsx b/src/components/ui/sheet.tsx deleted file mode 100644 index 4b7f44a..0000000 --- a/src/components/ui/sheet.tsx +++ /dev/null @@ -1,141 +0,0 @@ -import * as SheetPrimitive from "@radix-ui/react-dialog"; -import { type VariantProps, cva } from "class-variance-authority"; -import { X } from "lucide-react"; -import * as React from "react"; - -import { cn } from "@/lib/utils"; - -const Sheet = SheetPrimitive.Root; - -const SheetTrigger = SheetPrimitive.Trigger; - -const SheetClose = SheetPrimitive.Close; - -const SheetPortal = SheetPrimitive.Portal; - -const SheetOverlay = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -SheetOverlay.displayName = SheetPrimitive.Overlay.displayName; - -const sheetVariants = cva( - "fixed z-50 gap-4 bg-white p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500 dark:bg-neutral-950", - { - variants: { - side: { - top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top", - bottom: - "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom", - left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm", - right: - "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm", - }, - }, - defaultVariants: { - side: "right", - }, - }, -); - -interface SheetContentProps - extends React.ComponentPropsWithoutRef, - VariantProps {} - -const SheetContent = React.forwardRef< - React.ElementRef, - SheetContentProps ->(({ side = "right", className, children, ...props }, ref) => ( - - - - {children} - - - Close - - - -)); -SheetContent.displayName = SheetPrimitive.Content.displayName; - -const SheetHeader = ({ - className, - ...props -}: React.HTMLAttributes) => ( -
-); -SheetHeader.displayName = "SheetHeader"; - -const SheetFooter = ({ - className, - ...props -}: React.HTMLAttributes) => ( -
-); -SheetFooter.displayName = "SheetFooter"; - -const SheetTitle = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -SheetTitle.displayName = SheetPrimitive.Title.displayName; - -const SheetDescription = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -SheetDescription.displayName = SheetPrimitive.Description.displayName; - -export { - Sheet, - SheetPortal, - SheetOverlay, - SheetTrigger, - SheetClose, - SheetContent, - SheetHeader, - SheetFooter, - SheetTitle, - SheetDescription, -}; diff --git a/src/components/ui/slider.tsx b/src/components/ui/slider.tsx new file mode 100644 index 0000000..a2e41bc --- /dev/null +++ b/src/components/ui/slider.tsx @@ -0,0 +1,26 @@ +import * as SliderPrimitive from "@radix-ui/react-slider"; +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const Slider = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + + +)); +Slider.displayName = SliderPrimitive.Root.displayName; + +export { Slider }; diff --git a/src/consts/chart.ts b/src/consts/chart.ts index 33d1c28..5ff43e3 100644 --- a/src/consts/chart.ts +++ b/src/consts/chart.ts @@ -18,3 +18,5 @@ export const displayDataType: Record = { usage: "Usage", clock: "Clock", } as const; + +export const sizeOptions = ["sm", "md", "lg", "xl", "2xl"] as const; diff --git a/src/index.css b/src/index.css index 95d8cab..d1e18c8 100644 --- a/src/index.css +++ b/src/index.css @@ -5,77 +5,56 @@ @layer base { :root { --background: 0 0% 100%; - --foreground: 222.2 47.4% 11.2%; - - --muted: 210 40% 96.1%; - --muted-foreground: 215.4 16.3% 46.9%; - - --popover: 0 0% 100%; - --popover-foreground: 222.2 47.4% 11.2%; - - --border: 214.3 31.8% 91.4%; - --input: 214.3 31.8% 91.4%; - + --foreground: 222.2 84% 4.9%; --card: 0 0% 100%; - --card-foreground: 222.2 47.4% 11.2%; - + --card-foreground: 222.2 84% 4.9%; + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; --primary: 222.2 47.4% 11.2%; --primary-foreground: 210 40% 98%; - --secondary: 210 40% 96.1%; --secondary-foreground: 222.2 47.4% 11.2%; - + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; --accent: 210 40% 96.1%; --accent-foreground: 222.2 47.4% 11.2%; - - --destructive: 0 100% 50%; + --destructive: 0 84.2% 60.2%; --destructive-foreground: 210 40% 98%; - - --ring: 215 20.2% 65.1%; - - --radius: 0.5rem; + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 222.2 84% 4.9%; + --radius: 1rem; + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; } .dark { - --background: 224 71% 4%; - --foreground: 213 31% 91%; - - --muted: 223 47% 11%; - --muted-foreground: 215.4 16.3% 56.9%; - - --accent: 216 34% 17%; - --accent-foreground: 210 40% 98%; - - --popover: 224 71% 4%; - --popover-foreground: 215 20.2% 65.1%; - - --border: 216 34% 17%; - --input: 216 34% 17%; - - --card: 224 71% 4%; - --card-foreground: 213 31% 91%; - + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; --primary: 210 40% 98%; - --primary-foreground: 222.2 47.4% 1.2%; - - --secondary: 222.2 47.4% 11.2%; + --primary-foreground: 222.2 47.4% 11.2%; + --secondary: 217.2 32.6% 17.5%; --secondary-foreground: 210 40% 98%; - - --destructive: 0 63% 31%; + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; + --destructive: 0 62.8% 30.6%; --destructive-foreground: 210 40% 98%; - - --ring: 216 34% 17%; - - --radius: 0.5rem; - } -} - -@layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - font-feature-settings: "rlig" 1, "calt" 1; + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + --ring: 212.7 26.8% 83.9; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; } } diff --git a/src/services/settingService.ts b/src/services/settingService.ts index 3eec3ad..4ddb3df 100644 --- a/src/services/settingService.ts +++ b/src/services/settingService.ts @@ -14,3 +14,13 @@ export const setDisplayTargets = async ( ): Promise => { return await invoke("set_display_targets", { newTargets: targets }); }; + +export const setGraphSize = async ( + size: Settings["graphSize"], +): Promise => { + return await invoke("set_graph_size", { newSize: size }); +}; + +export const setLanguage = async (value: string): Promise => { + return await invoke("set_language", { newLanguage: value }); +}; diff --git a/src/template/Dashboard.tsx b/src/template/Dashboard.tsx index fa24444..c6882c4 100644 --- a/src/template/Dashboard.tsx +++ b/src/template/Dashboard.tsx @@ -155,7 +155,7 @@ const MemoryInfo = () => { const Dashboard = () => { return ( -
+ <>
@@ -173,7 +173,7 @@ const Dashboard = () => {
-
+ ); }; diff --git a/src/template/ScreenTemplate.tsx b/src/template/ScreenTemplate.tsx new file mode 100644 index 0000000..f92fc37 --- /dev/null +++ b/src/template/ScreenTemplate.tsx @@ -0,0 +1,15 @@ +interface ScreenTemplateProps { + title?: string; + children: React.ReactNode; +} + +const ScreenTemplate: React.FC = ({ title, children }) => { + return ( +
+ {title &&

{title}

} + {children} +
+ ); +}; + +export default ScreenTemplate; diff --git a/src/template/Settings.tsx b/src/template/Settings.tsx new file mode 100644 index 0000000..7e33b0e --- /dev/null +++ b/src/template/Settings.tsx @@ -0,0 +1,123 @@ +import { useSettingsAtom } from "@/atom/useSettingsAtom"; +import { Label } from "@/components/ui/label"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Slider } from "@/components/ui/slider"; +import { sizeOptions } from "@/consts/chart"; +import type { ChartDataType } from "@/types/hardwareDataType"; +import type { Settings as SettingTypes } from "@/types/settingsType"; + +const SettingGraphType = () => { + const { settings, toggleDisplayTarget } = useSettingsAtom(); + const selectedGraphTypes = settings.display_targets; + + const toggleGraphType = async (type: ChartDataType) => { + await toggleDisplayTarget(type); + }; + + return ( +
+ +
+ + + +
+
+ ); +}; + +const SettingColorMode = () => { + const { settings, updateSettingAtom } = useSettingsAtom(); + + const toggleDarkMode = async (mode: "light" | "dark") => { + await updateSettingAtom("theme", mode); + }; + + return ( +
+ + +
+ ); +}; + +const SettingLineChartSize = () => { + const { settings, updateSettingAtom } = useSettingsAtom(); + const sizeIndex = sizeOptions.indexOf( + settings.graphSize as SettingTypes["graphSize"], + ); + + const changeGraphSize = async (value: number[]) => { + await updateSettingAtom("graphSize", sizeOptions[value[0]]); + }; + + return ( +
+ + +
+ {sizeOptions.map((size) => ( + {size.toUpperCase()} + ))} +
+
+ ); +}; + +const Settings = () => { + return ( + <> + + + + + ); +}; + +export default Settings; diff --git a/src/template/SettingsSheet.tsx b/src/template/SettingsSheet.tsx deleted file mode 100644 index 2e0d142..0000000 --- a/src/template/SettingsSheet.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { modalAtoms } from "@/atom/ui"; -import { useSettingsAtom } from "@/atom/useSettingsAtom"; -import { Button } from "@/components/ui/button"; -import { Label } from "@/components/ui/label"; -import { - Sheet, - SheetContent, - SheetDescription, - SheetHeader, - SheetTitle, -} from "@/components/ui/sheet"; -import { useSettingsModalListener } from "@/hooks/useTauriEventListener"; -import type { ChartDataType } from "@/types/hardwareDataType"; -import { useAtom } from "jotai"; - -const SettingGraphType = () => { - const { settings, toggleDisplayTarget } = useSettingsAtom(); - const selectedGraphTypes = settings.display_targets; - - const toggleGraphType = async (type: ChartDataType) => { - await toggleDisplayTarget(type); - }; - - return ( -
- -
- - - -
-
- ); -}; - -const SettingColorMode = () => { - const { settings, toggleTheme } = useSettingsAtom(); - - const toggleDarkMode = async (mode: "light" | "dark") => { - await toggleTheme(mode); - }; - - return ( -
- -
- - -
-
- ); -}; - -const SettingsSheet = () => { - const [showSettingsModal] = useAtom(modalAtoms.showSettingsModal); - const { closeModal } = useSettingsModalListener(); - - return ( - - - - Edit Preference - - Make changes to your preferences here. Click save when you're done. - - -
- - -
-
-
- ); -}; - -export default SettingsSheet; diff --git a/src/types/settingsType.ts b/src/types/settingsType.ts index 0bf75b4..4d842ee 100644 --- a/src/types/settingsType.ts +++ b/src/types/settingsType.ts @@ -1,7 +1,9 @@ +import type { sizeOptions } from "@/consts/chart"; import type { ChartDataType } from "./hardwareDataType"; export type Settings = { language: string; theme: "light" | "dark"; display_targets: Array; + graphSize: (typeof sizeOptions)[number]; };