feat(profile): display version number from .env in profile menu

This commit is contained in:
Shivam Kumar
2025-09-05 16:30:09 +05:30
parent 25e5b61b3e
commit 23f6c65a14
6 changed files with 42 additions and 1 deletions

17
package-lock.json generated
View File

@@ -96,6 +96,7 @@
"eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20", "eslint-plugin-react-refresh": "^0.4.20",
"globals": "^16.3.0", "globals": "^16.3.0",
"prettier": "^3.6.2",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"tw-animate-css": "^1.3.5", "tw-animate-css": "^1.3.5",
"typescript": "~5.9.2", "typescript": "~5.9.2",
@@ -7558,6 +7559,22 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/prettier": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/proxy-addr": { "node_modules/proxy-addr": {
"version": "2.0.7", "version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",

View File

@@ -100,6 +100,7 @@
"eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20", "eslint-plugin-react-refresh": "^0.4.20",
"globals": "^16.3.0", "globals": "^16.3.0",
"prettier": "^3.6.2",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"tw-animate-css": "^1.3.5", "tw-animate-css": "^1.3.5",
"typescript": "~5.9.2", "typescript": "~5.9.2",

View File

@@ -72,6 +72,7 @@
"register": "Register", "register": "Register",
"username": "Username", "username": "Username",
"password": "Password", "password": "Password",
"version" : "Version",
"confirmPassword": "Confirm Password", "confirmPassword": "Confirm Password",
"back": "Back", "back": "Back",
"email": "Email", "email": "Email",

View File

@@ -1,6 +1,6 @@
import * as React from "react" import * as React from "react"
import { Slot } from "@radix-ui/react-slot" import { Slot } from "@radix-ui/react-slot"
import { cva, VariantProps } from "class-variance-authority" import { cva, type VariantProps } from "class-variance-authority"
import { PanelLeftIcon } from "lucide-react" import { PanelLeftIcon } from "lucide-react"
import { useIsMobile } from "@/hooks/use-mobile" import { useIsMobile } from "@/hooks/use-mobile"

View File

@@ -8,11 +8,13 @@ import {Tabs, TabsContent, TabsList, TabsTrigger} from "@/components/ui/tabs.tsx
import {User, Shield, Key, AlertCircle} from "lucide-react"; import {User, Shield, Key, AlertCircle} from "lucide-react";
import {TOTPSetup} from "@/ui/User/TOTPSetup.tsx"; import {TOTPSetup} from "@/ui/User/TOTPSetup.tsx";
import {getUserInfo} from "@/ui/main-axios.ts"; import {getUserInfo} from "@/ui/main-axios.ts";
import { getVersionInfo } from "@/ui/main-axios.ts";
import {toast} from "sonner"; import {toast} from "sonner";
import {PasswordReset} from "@/ui/User/PasswordReset.tsx"; import {PasswordReset} from "@/ui/User/PasswordReset.tsx";
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import {LanguageSwitcher} from "@/components/LanguageSwitcher"; import {LanguageSwitcher} from "@/components/LanguageSwitcher";
interface UserProfileProps { interface UserProfileProps {
isTopbarOpen?: boolean; isTopbarOpen?: boolean;
} }
@@ -27,11 +29,23 @@ export function UserProfile({isTopbarOpen = true}: UserProfileProps) {
} | null>(null); } | null>(null);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [versionInfo, setVersionInfo] = useState<{ version: string } | null>(null);
useEffect(() => { useEffect(() => {
fetchUserInfo(); fetchUserInfo();
fetchVersion();
}, []); }, []);
const fetchVersion = async () => {
try {
const info = await getVersionInfo();
setVersionInfo({ version: info.version });
} catch (err) {
console.error("Failed to load version info", err);
}
};
const fetchUserInfo = async () => { const fetchUserInfo = async () => {
setLoading(true); setLoading(true);
setError(null); setError(null);
@@ -146,6 +160,13 @@ export function UserProfile({isTopbarOpen = true}: UserProfileProps) {
)} )}
</p> </p>
</div> </div>
<div>
<Label>{t('common.version')}</Label>
<p className="text-lg font-medium mt-1">
{versionInfo?.version || t('common.loading')}
</p>
</div>
</div> </div>
<div className="mt-6 pt-6 border-t"> <div className="mt-6 pt-6 border-t">

View File

@@ -140,6 +140,7 @@ interface AuthResponse {
} }
interface UserInfo { interface UserInfo {
totp_enabled: boolean;
id: string; id: string;
username: string; username: string;
is_admin: boolean; is_admin: boolean;