From 121eb8a11cddb2d679b0d6223a3b558fe419ac55 Mon Sep 17 00:00:00 2001 From: Friedrich482 Date: Thu, 5 Mar 2026 16:46:17 +0100 Subject: [PATCH 1/3] chore: extension version - bumped the extension version to `v0.0.53` --- apps/vscode-extension/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vscode-extension/package.json b/apps/vscode-extension/package.json index f5c60f4..6092b5c 100644 --- a/apps/vscode-extension/package.json +++ b/apps/vscode-extension/package.json @@ -2,7 +2,7 @@ "name": "mooncode", "displayName": "MoonCode", "description": "MoonCode is an extension that tracks your coding time (like WakaTime) and gives you a detailed summary about all your coding statistics. With MoonCode, developers get the full history of their coding activity.", - "version": "0.0.52", + "version": "0.0.53", "icon": "./public/moon.png", "publisher": "Friedrich482", "author": { From 2d27b882ec38564861d98d52791548db51b45f78 Mon Sep 17 00:00:00 2001 From: Friedrich482 Date: Thu, 5 Mar 2026 17:02:10 +0100 Subject: [PATCH 2/3] fix: dashboard - added the `VITE_LINKING_GOOGLE_ACCOUNT_URL` in the environment of the `publish-extension.yaml` ci/cd - bumped the extension version to `v0.0.54` --- .github/workflows/publish-extension.yaml | 1 + apps/vscode-extension/package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-extension.yaml b/.github/workflows/publish-extension.yaml index 51dceb4..2366c13 100644 --- a/.github/workflows/publish-extension.yaml +++ b/.github/workflows/publish-extension.yaml @@ -31,3 +31,4 @@ jobs: VITE_API_URL: ${{secrets.VITE_API_URL}} VITE_LOGOUT_URL: ${{secrets.VITE_LOGOUT_URL}} VITE_AUTH_GOOGLE_URL: ${{secrets.VITE_AUTH_GOOGLE_URL}} + VITE_LINKING_GOOGLE_ACCOUNT_URL: ${{secrets.VITE_LINKING_GOOGLE_ACCOUNT_URL}} diff --git a/apps/vscode-extension/package.json b/apps/vscode-extension/package.json index 6092b5c..0c322e4 100644 --- a/apps/vscode-extension/package.json +++ b/apps/vscode-extension/package.json @@ -2,7 +2,7 @@ "name": "mooncode", "displayName": "MoonCode", "description": "MoonCode is an extension that tracks your coding time (like WakaTime) and gives you a detailed summary about all your coding statistics. With MoonCode, developers get the full history of their coding activity.", - "version": "0.0.53", + "version": "0.0.54", "icon": "./public/moon.png", "publisher": "Friedrich482", "author": { From fd36f05a4df7ea88b7f491deeff43a4e67329c03 Mon Sep 17 00:00:00 2001 From: Friedrich482 Date: Fri, 6 Mar 2026 22:34:43 +0100 Subject: [PATCH 3/3] feat: web app - added the header on the web app with support for dark mode using the right primitives for nextjs: next-themes for the theme-provider instead of the default provider coming for react+vite - installed `turbopack-inline-svg-loader` to properly import and render the logo as an svg instead of an image in the web app header, similarly to vite - installed the `prettier-plugin-tailwindcss` in the web app --- apps/dashboard/src/App.tsx | 2 +- .../layout/header/navbar-dropdowns.tsx | 9 +- .../src/providers/theme-provider.tsx | 78 + apps/web/.prettierrc | 3 + apps/web/next.config.ts | 11 + apps/web/package.json | 5 + apps/web/src/app/layout.tsx | 17 +- apps/web/src/app/page.tsx | 2 +- apps/web/src/assets/moon.svg | 16 + apps/web/src/components/layout/footer.tsx | 3 + .../layout/header/header-additional-links.tsx | 24 + .../src/components/layout/header/header.tsx | 13 + .../src/components/layout/header/navbar.tsx | 22 + .../layout/header/theme-toggler.tsx | 22 + .../src/components/layout/header/title.tsx | 16 + apps/web/src/constants.ts | 30 + apps/web/src/providers/theme-provider.tsx | 18 + apps/web/svg.d.ts | 14 + package-lock.json | 2114 ++++++++++++++++- packages/ui/package.json | 3 +- .../src/components/toggle-theme-dropdown.tsx | 15 +- packages/ui/src/components/ui/sonner.tsx | 2 +- packages/ui/src/types-schemas.ts | 1 + 23 files changed, 2299 insertions(+), 141 deletions(-) create mode 100644 apps/dashboard/src/providers/theme-provider.tsx create mode 100644 apps/web/.prettierrc create mode 100644 apps/web/src/assets/moon.svg create mode 100644 apps/web/src/components/layout/footer.tsx create mode 100644 apps/web/src/components/layout/header/header-additional-links.tsx create mode 100644 apps/web/src/components/layout/header/header.tsx create mode 100644 apps/web/src/components/layout/header/navbar.tsx create mode 100644 apps/web/src/components/layout/header/theme-toggler.tsx create mode 100644 apps/web/src/components/layout/header/title.tsx create mode 100644 apps/web/src/constants.ts create mode 100644 apps/web/src/providers/theme-provider.tsx create mode 100644 apps/web/svg.d.ts diff --git a/apps/dashboard/src/App.tsx b/apps/dashboard/src/App.tsx index 0ee925a..720b4c4 100644 --- a/apps/dashboard/src/App.tsx +++ b/apps/dashboard/src/App.tsx @@ -10,7 +10,6 @@ import { ScrollToTopButton } from "@repo/ui/components/scroll-to-top-button"; import { SidebarProvider } from "@repo/ui/components/ui/sidebar"; import { Toaster } from "@repo/ui/components/ui/sonner"; import { TooltipProvider } from "@repo/ui/components/ui/tooltip"; -import { ThemeProvider } from "@repo/ui/providers/theme-provider"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; import { createTRPCClient, httpBatchLink } from "@trpc/client"; @@ -18,6 +17,7 @@ import { createTRPCClient, httpBatchLink } from "@trpc/client"; import { FallBackRender } from "./components/errors/error-boundary"; import { Wrapper } from "./components/layout/navigation-reset-wrapper"; import { useExtensionWebsocket } from "./hooks/use-extension-websocket"; +import { ThemeProvider } from "./providers/theme-provider"; import { TRPCProvider } from "./utils/trpc"; function makeQueryClient() { diff --git a/apps/dashboard/src/components/layout/header/navbar-dropdowns.tsx b/apps/dashboard/src/components/layout/header/navbar-dropdowns.tsx index bccff17..c72196c 100644 --- a/apps/dashboard/src/components/layout/header/navbar-dropdowns.tsx +++ b/apps/dashboard/src/components/layout/header/navbar-dropdowns.tsx @@ -1,11 +1,18 @@ +import { useTheme } from "@/providers/theme-provider"; import { ToggleThemeDropDown } from "@repo/ui/components/toggle-theme-dropdown"; import { AuthDropDown } from "./auth-dropdown"; export const NavbarDropDowns = () => { + const { theme: providedTheme, setTheme, resolvedTheme } = useTheme(); + return (
- +
); diff --git a/apps/dashboard/src/providers/theme-provider.tsx b/apps/dashboard/src/providers/theme-provider.tsx new file mode 100644 index 0000000..813248e --- /dev/null +++ b/apps/dashboard/src/providers/theme-provider.tsx @@ -0,0 +1,78 @@ +import { createContext, useContext, useEffect, useState } from "react"; + +import { ResolvedTheme, Theme } from "@repo/ui/types-schemas"; + +type ThemeProviderProps = { + children: React.ReactNode; + defaultTheme?: Theme; + storageKey?: string; +}; + +type ThemeProviderState = { + theme: Theme; + setTheme: (theme: Theme) => void; + resolvedTheme: ResolvedTheme; +}; + +const initialState: ThemeProviderState = { + theme: "system", + setTheme: () => null, + resolvedTheme: "light", +}; + +const ThemeProviderContext = createContext(initialState); + +export const ThemeProvider = ({ + children, + defaultTheme = "system", + storageKey = "vite-ui-theme", + ...props +}: ThemeProviderProps) => { + const [theme, setTheme] = useState( + () => (localStorage.getItem(storageKey) as Theme) || defaultTheme, + ); + const [resolvedTheme, setResolvedTheme] = useState("light"); + + useEffect(() => { + const root = window.document.documentElement; + + root.classList.remove("light", "dark"); + + let newTheme: ResolvedTheme; + + if (theme === "system") { + newTheme = window.matchMedia("(prefers-color-scheme: dark)").matches + ? "dark" + : "light"; + } else { + newTheme = theme; + } + + root.classList.add(newTheme); + setResolvedTheme(newTheme); + }, [theme]); + + const value = { + theme, + resolvedTheme, + setTheme: (theme: Theme) => { + localStorage.setItem(storageKey, theme); + setTheme(theme); + }, + }; + + return ( + + {children} + + ); +}; + +export const useTheme = () => { + const context = useContext(ThemeProviderContext); + + if (context === undefined) + throw new Error("useTheme must be used within a ThemeProvider"); + + return context; +}; diff --git a/apps/web/.prettierrc b/apps/web/.prettierrc new file mode 100644 index 0000000..b4bfed3 --- /dev/null +++ b/apps/web/.prettierrc @@ -0,0 +1,3 @@ +{ + "plugins": ["prettier-plugin-tailwindcss"] +} diff --git a/apps/web/next.config.ts b/apps/web/next.config.ts index 68a6c64..070adf9 100644 --- a/apps/web/next.config.ts +++ b/apps/web/next.config.ts @@ -2,6 +2,17 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { output: "standalone", + turbopack: { + rules: { + "*.svg": { + loaders: ["turbopack-inline-svg-loader"], + condition: { + content: /^[\s\S]{0,4000}$/, // <-- Inline SVGs smaller than ~4Kb + }, + as: "*.js", + }, + }, + }, }; export default nextConfig; diff --git a/apps/web/package.json b/apps/web/package.json index e047bea..f6c599d 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -9,6 +9,7 @@ "lint": "eslint . --fix" }, "dependencies": { + "@icons-pack/react-simple-icons": "^13.11.1", "@repo/common": "*", "@repo/trpc": "*", "@repo/ui": "*", @@ -18,6 +19,7 @@ "react-dom": "^19.2.0" }, "devDependencies": { + "@svgr/webpack": "^8.1.0", "@types/node": "^20.19.32", "@types/react": "^19.2.5", "@types/react-dom": "^19.2.3", @@ -25,7 +27,10 @@ "eslint": "^9.39.2", "eslint-config-next": "^16.0.3", "postcss": "^8.5.6", + "prettier": "^3.8.1", + "prettier-plugin-tailwindcss": "^0.6.14", "tailwindcss": "^4.1.17", + "turbopack-inline-svg-loader": "^1.0.3", "typescript": "^5.9.3" }, "overrides": { diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx index 4e148e8..941c199 100644 --- a/apps/web/src/app/layout.tsx +++ b/apps/web/src/app/layout.tsx @@ -1,7 +1,10 @@ import type { Metadata } from "next"; -import { ThemeProvider } from "next-themes"; import { Inter } from "next/font/google"; +import { Footer } from "@/components/layout/footer"; +import { Header } from "@/components/layout/header/header"; +import { ThemeProvider } from "@/providers/theme-provider"; + import "@repo/ui/globals.css"; const inter = Inter({ subsets: ["latin"] }); @@ -18,9 +21,17 @@ export default function RootLayout({ }>) { return ( - - + + + +
{children} +