From 5e9ebaf19fef192adcfca6e959db473ecbc25d66 Mon Sep 17 00:00:00 2001 From: Ben Senescu <44480372+bensenescu@users.noreply.github.com> Date: Sat, 4 Apr 2026 18:47:32 -0400 Subject: [PATCH] fix ci (#79) --- src/client/layout/AppShell.tsx | 31 +++++++++++- src/routeTree.gen.ts | 21 ++++++++ src/routes/_app/support.tsx | 93 ++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 src/routes/_app/support.tsx diff --git a/src/client/layout/AppShell.tsx b/src/client/layout/AppShell.tsx index ad9dc7b..8e77669 100644 --- a/src/client/layout/AppShell.tsx +++ b/src/client/layout/AppShell.tsx @@ -1,6 +1,12 @@ import * as React from "react"; import { Link, useLocation } from "@tanstack/react-router"; -import { ChevronsUpDown, CreditCard, Menu, User } from "lucide-react"; +import { + ChevronsUpDown, + CircleHelp, + CreditCard, + Menu, + User, +} from "lucide-react"; import { AppContent, MissingSeoSetupModal, @@ -15,6 +21,7 @@ import { BILLING_ROUTE } from "@/shared/billing"; import { getSeoApiKeyStatus } from "@/serverFunctions/config"; const DATAFORSEO_HELP_PATH = "/help/dataforseo-api-key"; +const SUPPORT_PATH = "/support"; export function AuthenticatedAppLayout({ children, @@ -142,6 +149,7 @@ function TopNav({ onOpenDrawer: () => void; }) { const projectNavItems = projectId ? getProjectNavItems(projectId) : []; + const isSupportActive = pathname === SUPPORT_PATH; return (
@@ -192,6 +200,19 @@ function TopNav({
+
+ + + +
+
{email} ) : null} + {mobileOnly ? ( +
  • + + + Help & Community + +
  • + ) : null} {isHostedMode ? (
  • diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts index 17ef7af..1797ac9 100644 --- a/src/routeTree.gen.ts +++ b/src/routeTree.gen.ts @@ -20,6 +20,7 @@ import { Route as AppIndexRouteImport } from './routes/_app/index' import { Route as AuthenticatedSubscribeRouteImport } from './routes/_authenticated.subscribe' import { Route as AuthSignUpRouteImport } from './routes/_auth.sign-up' import { Route as AuthSignInRouteImport } from './routes/_auth.sign-in' +import { Route as AppSupportRouteImport } from './routes/_app/support' import { Route as AppBillingRouteImport } from './routes/_app/billing' import { Route as ApiAutumnSplatRouteImport } from './routes/api/autumn/$' import { Route as ApiAuthSplatRouteImport } from './routes/api/auth/$' @@ -86,6 +87,11 @@ const AuthSignInRoute = AuthSignInRouteImport.update({ path: '/sign-in', getParentRoute: () => AuthRoute, } as any) +const AppSupportRoute = AppSupportRouteImport.update({ + id: '/support', + path: '/support', + getParentRoute: () => AppRouteRoute, +} as any) const AppBillingRoute = AppBillingRouteImport.update({ id: '/billing', path: '/billing', @@ -167,6 +173,7 @@ export interface FileRoutesByFullPath { '/reset-password': typeof ResetPasswordRoute '/verify-email': typeof VerifyEmailRoute '/billing': typeof AppBillingRoute + '/support': typeof AppSupportRoute '/sign-in': typeof AuthSignInRoute '/sign-up': typeof AuthSignUpRoute '/subscribe': typeof AuthenticatedSubscribeRoute @@ -190,6 +197,7 @@ export interface FileRoutesByTo { '/reset-password': typeof ResetPasswordRoute '/verify-email': typeof VerifyEmailRoute '/billing': typeof AppBillingRoute + '/support': typeof AppSupportRoute '/sign-in': typeof AuthSignInRoute '/sign-up': typeof AuthSignUpRoute '/subscribe': typeof AuthenticatedSubscribeRoute @@ -215,6 +223,7 @@ export interface FileRoutesById { '/reset-password': typeof ResetPasswordRoute '/verify-email': typeof VerifyEmailRoute '/_app/billing': typeof AppBillingRoute + '/_app/support': typeof AppSupportRoute '/_auth/sign-in': typeof AuthSignInRoute '/_auth/sign-up': typeof AuthSignUpRoute '/_authenticated/subscribe': typeof AuthenticatedSubscribeRoute @@ -241,6 +250,7 @@ export interface FileRouteTypes { | '/reset-password' | '/verify-email' | '/billing' + | '/support' | '/sign-in' | '/sign-up' | '/subscribe' @@ -264,6 +274,7 @@ export interface FileRouteTypes { | '/reset-password' | '/verify-email' | '/billing' + | '/support' | '/sign-in' | '/sign-up' | '/subscribe' @@ -288,6 +299,7 @@ export interface FileRouteTypes { | '/reset-password' | '/verify-email' | '/_app/billing' + | '/_app/support' | '/_auth/sign-in' | '/_auth/sign-up' | '/_authenticated/subscribe' @@ -398,6 +410,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AuthSignInRouteImport parentRoute: typeof AuthRoute } + '/_app/support': { + id: '/_app/support' + path: '/support' + fullPath: '/support' + preLoaderRoute: typeof AppSupportRouteImport + parentRoute: typeof AppRouteRoute + } '/_app/billing': { id: '/_app/billing' path: '/billing' @@ -501,12 +520,14 @@ declare module '@tanstack/react-router' { interface AppRouteRouteChildren { AppBillingRoute: typeof AppBillingRoute + AppSupportRoute: typeof AppSupportRoute AppIndexRoute: typeof AppIndexRoute AppHelpDataforseoApiKeyRoute: typeof AppHelpDataforseoApiKeyRoute } const AppRouteRouteChildren: AppRouteRouteChildren = { AppBillingRoute: AppBillingRoute, + AppSupportRoute: AppSupportRoute, AppIndexRoute: AppIndexRoute, AppHelpDataforseoApiKeyRoute: AppHelpDataforseoApiKeyRoute, } diff --git a/src/routes/_app/support.tsx b/src/routes/_app/support.tsx new file mode 100644 index 0000000..a3bdce7 --- /dev/null +++ b/src/routes/_app/support.tsx @@ -0,0 +1,93 @@ +import { createFileRoute } from "@tanstack/react-router"; +import { Check, Copy } from "lucide-react"; +import { useState } from "react"; +import { toast } from "sonner"; + +const SUPPORT_EMAIL = "ben@openseo.so"; +const DISCORD_URL = "https://discord.gg/c9uGs3cFXr"; +const GITHUB_URL = "https://github.com/every-app/open-seo"; + +export const Route = createFileRoute("/_app/support")({ + component: SupportPage, +}); + +function SupportPage() { + const [copied, setCopied] = useState(false); + + const handleCopy = async () => { + await navigator.clipboard.writeText(SUPPORT_EMAIL); + toast.success("Email copied to clipboard"); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }; + + return ( + + ); +}