diff --git a/packages/frontend/src/Index.tsx b/packages/frontend/src/Index.tsx index 97dcaab..eee38b9 100644 --- a/packages/frontend/src/Index.tsx +++ b/packages/frontend/src/Index.tsx @@ -17,12 +17,10 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; -import { getAuthHeaders } from "@/lib/utils"; +import { getAuthHeaders, getServerURL } from "@/lib/utils"; import { ResizablePanel, ResizablePanelGroup, ResizableSeparator } from "./components/ui/resizable"; function Index() { - const serverURL = import.meta.env.VITE_SERVER_URL?.trim() || "http://localhost:3000"; - const user = JSON.parse(localStorage.getItem("user") || "{}") as UserRecord; const organisationsRef = useRef(false); @@ -37,7 +35,7 @@ function Index() { const refetchOrganisations = async (options?: { selectOrganisationId?: number }) => { try { - const res = await fetch(`${serverURL}/organisation/by-user?userId=${user.id}`, { + const res = await fetch(`${getServerURL()}/organisation/by-user?userId=${user.id}`, { headers: getAuthHeaders(), }); const data = (await res.json()) as Array; @@ -77,7 +75,7 @@ function Index() { const refetchProjects = async (organisationId: number, options?: { selectProjectId?: number }) => { try { const res = await fetch( - `${serverURL}/projects/by-organisation?organisationId=${organisationId}`, + `${getServerURL()}/projects/by-organisation?organisationId=${organisationId}`, { headers: getAuthHeaders(), }, @@ -126,7 +124,7 @@ function Index() { const refetchIssues = async (projectKey: string) => { try { - const res = await fetch(`${serverURL}/issues/${projectKey}`, { + const res = await fetch(`${getServerURL()}/issues/${projectKey}`, { headers: getAuthHeaders(), }); const data = (await res.json()) as IssueResponse[]; diff --git a/packages/frontend/src/Organisations.tsx b/packages/frontend/src/Organisations.tsx index 5110fec..20f5d0a 100644 --- a/packages/frontend/src/Organisations.tsx +++ b/packages/frontend/src/Organisations.tsx @@ -2,9 +2,7 @@ import type { OrganisationResponse, UserRecord } from "@issue/shared"; import { useCallback, useEffect, useState } from "react"; import { OrganisationSelect } from "@/components/organisation-select"; import { SettingsPageLayout } from "@/components/settings-page-layout"; -import { getAuthHeaders } from "@/lib/utils"; - -const SERVER_URL = import.meta.env.VITE_SERVER_URL?.trim() || "http://localhost:3000"; +import { getAuthHeaders, getServerURL } from "@/lib/utils"; function Organisations() { const user = JSON.parse(localStorage.getItem("user") || "{}") as UserRecord; @@ -15,7 +13,7 @@ function Organisations() { const refetchOrganisations = useCallback( async (options?: { selectOrganisationId?: number }) => { try { - const res = await fetch(`${SERVER_URL}/organisation/by-user?userId=${user.id}`, { + const res = await fetch(`${getServerURL()}/organisation/by-user?userId=${user.id}`, { headers: getAuthHeaders(), }); diff --git a/packages/frontend/src/components/auth-provider.tsx b/packages/frontend/src/components/auth-provider.tsx index 5c17bd8..6298eba 100644 --- a/packages/frontend/src/components/auth-provider.tsx +++ b/packages/frontend/src/components/auth-provider.tsx @@ -2,6 +2,7 @@ import type { UserRecord } from "@issue/shared"; import { useEffect, useRef, useState } from "react"; import Loading from "@/components/loading"; import LogInForm from "@/components/login-form"; +import { getServerURL } from "@/lib/utils"; type AuthProviderProps = { children: React.ReactNode; @@ -9,8 +10,6 @@ type AuthProviderProps = { }; export function Auth({ children }: AuthProviderProps) { - const serverURL = import.meta.env.VITE_SERVER_URL?.trim() || "http://localhost:3000"; - const [loggedIn, setLoggedIn] = useState(); const fetched = useRef(false); @@ -21,7 +20,7 @@ export function Auth({ children }: AuthProviderProps) { if (!token) { return setLoggedIn(false); } - fetch(`${serverURL}/auth/me`, { + fetch(`${getServerURL()}/auth/me`, { headers: { Authorization: `Bearer ${token}` }, }) .then(async (res) => { diff --git a/packages/frontend/src/components/create-issue.tsx b/packages/frontend/src/components/create-issue.tsx index ec4773d..94c2e2d 100644 --- a/packages/frontend/src/components/create-issue.tsx +++ b/packages/frontend/src/components/create-issue.tsx @@ -10,7 +10,7 @@ import { } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -import { cn, getAuthHeaders } from "@/lib/utils"; +import { cn, getAuthHeaders, getServerURL } from "@/lib/utils"; export function CreateIssue({ projectId, @@ -21,8 +21,6 @@ export function CreateIssue({ trigger?: React.ReactNode; completeAction?: (issueId: number) => void | Promise; }) { - const serverURL = import.meta.env.VITE_SERVER_URL?.trim() || "http://localhost:3000"; - const userId = JSON.parse(localStorage.getItem("user") || "{}").id as number | undefined; const [open, setOpen] = useState(false); @@ -90,7 +88,7 @@ export function CreateIssue({ setSubmitting(true); try { - const url = new URL(`${serverURL}/issue/create`); + const url = new URL(`${getServerURL()}/issue/create`); url.searchParams.set("projectId", `${projectId}`); url.searchParams.set("title", title.trim()); url.searchParams.set("description", description.trim()); diff --git a/packages/frontend/src/components/create-organisation.tsx b/packages/frontend/src/components/create-organisation.tsx index b4f246c..731660b 100644 --- a/packages/frontend/src/components/create-organisation.tsx +++ b/packages/frontend/src/components/create-organisation.tsx @@ -10,7 +10,7 @@ import { } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -import { cn, getAuthHeaders } from "@/lib/utils"; +import { cn, getAuthHeaders, getServerURL } from "@/lib/utils"; const slugify = (value: string) => value @@ -27,8 +27,6 @@ export function CreateOrganisation({ trigger?: React.ReactNode; completeAction?: (organisationId: number) => void | Promise; }) { - const serverURL = import.meta.env.VITE_SERVER_URL?.trim() || "http://localhost:3000"; - const userId = JSON.parse(localStorage.getItem("user") || "{}").id as number | undefined; const [open, setOpen] = useState(false); @@ -90,7 +88,7 @@ export function CreateOrganisation({ setSubmitting(true); try { - const url = new URL(`${serverURL}/organisation/create`); + const url = new URL(`${getServerURL()}/organisation/create`); url.searchParams.set("name", name.trim()); url.searchParams.set("slug", slug.trim()); url.searchParams.set("userId", `${userId}`); diff --git a/packages/frontend/src/components/create-project.tsx b/packages/frontend/src/components/create-project.tsx index a5eb401..65ff8d8 100644 --- a/packages/frontend/src/components/create-project.tsx +++ b/packages/frontend/src/components/create-project.tsx @@ -10,7 +10,7 @@ import { } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -import { cn, getAuthHeaders } from "@/lib/utils"; +import { cn, getAuthHeaders, getServerURL } from "@/lib/utils"; const keyify = (value: string) => value @@ -27,8 +27,6 @@ export function CreateProject({ trigger?: React.ReactNode; completeAction?: (projectId: number) => void | Promise; }) { - const serverURL = import.meta.env.VITE_SERVER_URL?.trim() || "http://localhost:3000"; - const userId = JSON.parse(localStorage.getItem("user") || "{}").id as number | undefined; const [open, setOpen] = useState(false); @@ -96,7 +94,7 @@ export function CreateProject({ setSubmitting(true); try { - const url = new URL(`${serverURL}/project/create`); + const url = new URL(`${getServerURL()}/project/create`); url.searchParams.set("key", key); url.searchParams.set("name", name.trim()); url.searchParams.set("creatorId", `${userId}`); diff --git a/packages/frontend/src/components/login-form.tsx b/packages/frontend/src/components/login-form.tsx index 4c286f0..587fe54 100644 --- a/packages/frontend/src/components/login-form.tsx +++ b/packages/frontend/src/components/login-form.tsx @@ -3,7 +3,7 @@ import { type ChangeEvent, useEffect, useMemo, useState } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -import { capitalise, cn } from "@/lib/utils"; +import { capitalise, cn, getServerURL } from "@/lib/utils"; function Field({ label = "label", @@ -46,8 +46,6 @@ function Field({ } export default function LogInForm() { - const serverURL = import.meta.env.VITE_SERVER_URL?.trim() || "http://localhost:3000"; - const [mode, setMode] = useState<"login" | "register">("login"); const [name, setName] = useState(""); @@ -79,7 +77,7 @@ export default function LogInForm() { return; } - fetch(`${serverURL}/auth/login`, { + fetch(`${getServerURL()}/auth/login`, { method: "POST", headers: { "Content-Type": "application/json" }, @@ -111,7 +109,7 @@ export default function LogInForm() { return; } - fetch(`${serverURL}/auth/register`, { + fetch(`${getServerURL()}/auth/register`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ diff --git a/packages/frontend/src/lib/utils.ts b/packages/frontend/src/lib/utils.ts index 89d7c3f..666043e 100644 --- a/packages/frontend/src/lib/utils.ts +++ b/packages/frontend/src/lib/utils.ts @@ -18,3 +18,16 @@ export function getAuthHeaders(): HeadersInit { export function capitalise(str: string) { return str.charAt(0).toUpperCase() + str.slice(1); } + +const ENV_SERVER_URL = import.meta.env.VITE_SERVER_URL?.trim(); + +export function getServerURL() { + let serverURL = + localStorage.getItem("serverURL") || // user-defined server URL + ENV_SERVER_URL || // environment variable + "https://eussi.ob248.com"; // fallback + if (serverURL.endsWith("/")) { + serverURL = serverURL.slice(0, -1); + } + return serverURL; +}