Move production to beenvoice.app with migrated accounts, refreshed auth and timer UX, and expanded invoice flows.

Official URL migration preserves sessions, shortcuts prefs, and last clock-in client; auth screens match web with legal links; time clock and invoice editor/send flows are updated for the new domain and UI patterns.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-26 03:40:48 -04:00
co-authored by Cursor
parent e17c4c6854
commit 6762a9bff3
60 changed files with 2544 additions and 1091 deletions
+5 -6
View File
@@ -13,16 +13,15 @@ import {
authStoragePrefix,
buildAccountId,
loadAccounts,
loadActiveAccountId,
loadDraftInstanceUrl,
saveAccounts,
saveActiveAccountId,
saveDraftInstanceUrl,
type SavedAccount,
} from "@/lib/accounts";
import { setRuntimeApiUrl, getApiUrl, DEFAULT_API_URL } from "@/lib/config";
import { setRuntimeApiUrl, getApiUrl, DEFAULT_API_URL, invalidServerUrlMessage } from "@/lib/config";
import { clearAuthStorage, readStoredSessionUser } from "@/lib/auth-storage";
import { normalizeInstanceUrl, saveStoredInstanceUrl } from "@/lib/instance-url";
import { migrateStoredOfficialUrls } from "@/lib/official-url-migration";
import { clearTimeClockPrefsForAccount } from "@/lib/time-clock-prefs";
export type RemoveAccountResult = {
@@ -58,8 +57,8 @@ export function AccountsProvider({ children }: { children: ReactNode }) {
const [apiUrl, setApiUrl] = useState(getApiUrl);
useEffect(() => {
Promise.all([loadAccounts(), loadActiveAccountId(), loadDraftInstanceUrl()])
.then(([storedAccounts, activeId, draftUrl]) => {
migrateStoredOfficialUrls()
.then(({ accounts: storedAccounts, activeAccountId: activeId, draftUrl }) => {
setAccounts(storedAccounts);
const active = storedAccounts.find((account) => account.id === activeId) ?? null;
@@ -86,7 +85,7 @@ export function AccountsProvider({ children }: { children: ReactNode }) {
async (url: string) => {
const normalized = normalizeInstanceUrl(url);
if (!normalized) {
throw new Error("Enter a valid server URL (e.g. beenvoice.app or localhost:3000)");
throw new Error(invalidServerUrlMessage());
}
if (activeAccount) {