diff --git a/apps/admin/react-router.config.ts b/apps/admin/react-router.config.ts index a4cef08832d..a2fbe61d82c 100644 --- a/apps/admin/react-router.config.ts +++ b/apps/admin/react-router.config.ts @@ -1,7 +1,12 @@ import type { Config } from "@react-router/dev/config"; -import { joinUrlPath } from "@plane/utils"; -const basePath = joinUrlPath(process.env.VITE_ADMIN_BASE_PATH ?? "", "/") ?? "/"; +const normalizeBasePath = (value: string): string => { + const trimmed = value.trim(); + if (!trimmed || trimmed === "/") return "/"; + return `/${trimmed.replace(/^\/+|\/+$/g, "")}/`; +}; + +const basePath = normalizeBasePath(process.env.VITE_ADMIN_BASE_PATH ?? ""); export default { appDirectory: "app", diff --git a/apps/admin/vite.config.ts b/apps/admin/vite.config.ts index c9d97157f41..b5bccf75c85 100644 --- a/apps/admin/vite.config.ts +++ b/apps/admin/vite.config.ts @@ -3,7 +3,12 @@ import * as dotenv from "@dotenvx/dotenvx"; import { reactRouter } from "@react-router/dev/vite"; import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; -import { joinUrlPath } from "@plane/utils"; + +const normalizeBasePath = (value: string): string => { + const trimmed = value.trim(); + if (!trimmed || trimmed === "/") return "/"; + return `/${trimmed.replace(/^\/+|\/+$/g, "")}/`; +}; dotenv.config({ path: path.resolve(__dirname, ".env") }); @@ -15,7 +20,7 @@ const viteEnv = Object.keys(process.env) return a; }, {}); -const basePath = joinUrlPath(process.env.VITE_ADMIN_BASE_PATH ?? "", "/") ?? "/"; +const basePath = normalizeBasePath(process.env.VITE_ADMIN_BASE_PATH ?? ""); export default defineConfig(() => ({ base: basePath, diff --git a/apps/space/react-router.config.ts b/apps/space/react-router.config.ts index 78a17439887..cb6db0d17a9 100644 --- a/apps/space/react-router.config.ts +++ b/apps/space/react-router.config.ts @@ -1,7 +1,12 @@ import type { Config } from "@react-router/dev/config"; -import { joinUrlPath } from "@plane/utils"; -const basePath = joinUrlPath(process.env.VITE_SPACE_BASE_PATH ?? "", "/") ?? "/"; +const normalizeBasePath = (value: string): string => { + const trimmed = value.trim(); + if (!trimmed || trimmed === "/") return "/"; + return `/${trimmed.replace(/^\/+|\/+$/g, "")}/`; +}; + +const basePath = normalizeBasePath(process.env.VITE_SPACE_BASE_PATH ?? ""); export default { appDirectory: "app", diff --git a/apps/space/vite.config.ts b/apps/space/vite.config.ts index 5368af0761c..0ef4a333b37 100644 --- a/apps/space/vite.config.ts +++ b/apps/space/vite.config.ts @@ -3,7 +3,12 @@ import * as dotenv from "@dotenvx/dotenvx"; import { reactRouter } from "@react-router/dev/vite"; import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; -import { joinUrlPath } from "@plane/utils"; + +const normalizeBasePath = (value: string): string => { + const trimmed = value.trim(); + if (!trimmed || trimmed === "/") return "/"; + return `/${trimmed.replace(/^\/+|\/+$/g, "")}/`; +}; dotenv.config({ path: path.resolve(__dirname, ".env") }); @@ -15,7 +20,7 @@ const viteEnv = Object.keys(process.env) return a; }, {}); -const basePath = joinUrlPath(process.env.VITE_SPACE_BASE_PATH ?? "", "/") ?? "/"; +const basePath = normalizeBasePath(process.env.VITE_SPACE_BASE_PATH ?? ""); export default defineConfig(() => ({ base: basePath, diff --git a/apps/web/core/components/home/user-greetings.tsx b/apps/web/core/components/home/user-greetings.tsx index 9fdb5598be5..c1ec465d82b 100644 --- a/apps/web/core/components/home/user-greetings.tsx +++ b/apps/web/core/components/home/user-greetings.tsx @@ -4,7 +4,6 @@ * See the LICENSE file for details. */ -import type { FC } from "react"; // plane types import { useTranslation } from "@plane/i18n"; import type { IUser } from "@plane/types"; @@ -23,23 +22,37 @@ export function UserGreetingsView(props: IUserGreetingsView) { // store hooks const { t } = useTranslation(); + // Use profile timezone when set to a real zone; treat UTC/Etc/UTC as unset (common + // backend default) so we show local time. Otherwise use browser/OS timezone. + const profileZone = user?.user_timezone?.trim(); + const isUtcDefault = + !profileZone || profileZone === "UTC" || profileZone === "Etc/UTC" || profileZone.toLowerCase() === "utc"; + const timeZone = isUtcDefault + ? typeof Intl !== "undefined" && Intl.DateTimeFormat + ? Intl.DateTimeFormat().resolvedOptions().timeZone + : undefined + : profileZone; + const hour = new Intl.DateTimeFormat("en-US", { hour12: false, hour: "numeric", + ...(timeZone && { timeZone }), }).format(currentTime); const date = new Intl.DateTimeFormat("en-US", { month: "short", day: "numeric", + ...(timeZone && { timeZone }), }).format(currentTime); const weekDay = new Intl.DateTimeFormat("en-US", { weekday: "long", + ...(timeZone && { timeZone }), }).format(currentTime); const timeString = new Intl.DateTimeFormat("en-US", { - timeZone: user?.user_timezone, - hour12: false, // Use 24-hour format + ...(timeZone && { timeZone }), + hour12: false, hour: "2-digit", minute: "2-digit", }).format(currentTime);