fix ci (#79)
This commit is contained in:
parent
bbed7c760a
commit
5e9ebaf19f
@ -1,6 +1,12 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Link, useLocation } from "@tanstack/react-router";
|
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 {
|
import {
|
||||||
AppContent,
|
AppContent,
|
||||||
MissingSeoSetupModal,
|
MissingSeoSetupModal,
|
||||||
@ -15,6 +21,7 @@ import { BILLING_ROUTE } from "@/shared/billing";
|
|||||||
import { getSeoApiKeyStatus } from "@/serverFunctions/config";
|
import { getSeoApiKeyStatus } from "@/serverFunctions/config";
|
||||||
|
|
||||||
const DATAFORSEO_HELP_PATH = "/help/dataforseo-api-key";
|
const DATAFORSEO_HELP_PATH = "/help/dataforseo-api-key";
|
||||||
|
const SUPPORT_PATH = "/support";
|
||||||
|
|
||||||
export function AuthenticatedAppLayout({
|
export function AuthenticatedAppLayout({
|
||||||
children,
|
children,
|
||||||
@ -142,6 +149,7 @@ function TopNav({
|
|||||||
onOpenDrawer: () => void;
|
onOpenDrawer: () => void;
|
||||||
}) {
|
}) {
|
||||||
const projectNavItems = projectId ? getProjectNavItems(projectId) : [];
|
const projectNavItems = projectId ? getProjectNavItems(projectId) : [];
|
||||||
|
const isSupportActive = pathname === SUPPORT_PATH;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="navbar shrink-0 gap-2 border-b border-base-300 bg-base-100">
|
<div className="navbar shrink-0 gap-2 border-b border-base-300 bg-base-100">
|
||||||
@ -192,6 +200,19 @@ function TopNav({
|
|||||||
<div className="flex-1" />
|
<div className="flex-1" />
|
||||||
|
|
||||||
<div className="hidden flex-none items-center gap-2 md:flex">
|
<div className="hidden flex-none items-center gap-2 md:flex">
|
||||||
|
<div className="tooltip tooltip-bottom" data-tip="Help & Community">
|
||||||
|
<Link
|
||||||
|
to={SUPPORT_PATH}
|
||||||
|
className={`btn btn-ghost btn-circle btn-sm ${
|
||||||
|
isSupportActive
|
||||||
|
? "bg-primary/10 text-primary"
|
||||||
|
: "text-base-content/60 hover:text-base-content"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<CircleHelp className="h-4 w-4" />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center rounded-full border border-base-300 bg-base-100/70 px-1 py-1 shadow-sm">
|
<div className="flex items-center rounded-full border border-base-300 bg-base-100/70 px-1 py-1 shadow-sm">
|
||||||
<div
|
<div
|
||||||
className="tooltip tooltip-left before:whitespace-nowrap"
|
className="tooltip tooltip-left before:whitespace-nowrap"
|
||||||
@ -254,6 +275,14 @@ function AccountMenu({ mobileOnly = false }: { mobileOnly?: boolean }) {
|
|||||||
<span className="truncate text-base-content">{email}</span>
|
<span className="truncate text-base-content">{email}</span>
|
||||||
</li>
|
</li>
|
||||||
) : null}
|
) : null}
|
||||||
|
{mobileOnly ? (
|
||||||
|
<li>
|
||||||
|
<Link to={SUPPORT_PATH} className="flex items-center gap-2">
|
||||||
|
<CircleHelp className="h-4 w-4" />
|
||||||
|
Help & Community
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
) : null}
|
||||||
{isHostedMode ? (
|
{isHostedMode ? (
|
||||||
<li>
|
<li>
|
||||||
<a href={BILLING_ROUTE} className="flex items-center gap-2">
|
<a href={BILLING_ROUTE} className="flex items-center gap-2">
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import { Route as AppIndexRouteImport } from './routes/_app/index'
|
|||||||
import { Route as AuthenticatedSubscribeRouteImport } from './routes/_authenticated.subscribe'
|
import { Route as AuthenticatedSubscribeRouteImport } from './routes/_authenticated.subscribe'
|
||||||
import { Route as AuthSignUpRouteImport } from './routes/_auth.sign-up'
|
import { Route as AuthSignUpRouteImport } from './routes/_auth.sign-up'
|
||||||
import { Route as AuthSignInRouteImport } from './routes/_auth.sign-in'
|
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 AppBillingRouteImport } from './routes/_app/billing'
|
||||||
import { Route as ApiAutumnSplatRouteImport } from './routes/api/autumn/$'
|
import { Route as ApiAutumnSplatRouteImport } from './routes/api/autumn/$'
|
||||||
import { Route as ApiAuthSplatRouteImport } from './routes/api/auth/$'
|
import { Route as ApiAuthSplatRouteImport } from './routes/api/auth/$'
|
||||||
@ -86,6 +87,11 @@ const AuthSignInRoute = AuthSignInRouteImport.update({
|
|||||||
path: '/sign-in',
|
path: '/sign-in',
|
||||||
getParentRoute: () => AuthRoute,
|
getParentRoute: () => AuthRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
const AppSupportRoute = AppSupportRouteImport.update({
|
||||||
|
id: '/support',
|
||||||
|
path: '/support',
|
||||||
|
getParentRoute: () => AppRouteRoute,
|
||||||
|
} as any)
|
||||||
const AppBillingRoute = AppBillingRouteImport.update({
|
const AppBillingRoute = AppBillingRouteImport.update({
|
||||||
id: '/billing',
|
id: '/billing',
|
||||||
path: '/billing',
|
path: '/billing',
|
||||||
@ -167,6 +173,7 @@ export interface FileRoutesByFullPath {
|
|||||||
'/reset-password': typeof ResetPasswordRoute
|
'/reset-password': typeof ResetPasswordRoute
|
||||||
'/verify-email': typeof VerifyEmailRoute
|
'/verify-email': typeof VerifyEmailRoute
|
||||||
'/billing': typeof AppBillingRoute
|
'/billing': typeof AppBillingRoute
|
||||||
|
'/support': typeof AppSupportRoute
|
||||||
'/sign-in': typeof AuthSignInRoute
|
'/sign-in': typeof AuthSignInRoute
|
||||||
'/sign-up': typeof AuthSignUpRoute
|
'/sign-up': typeof AuthSignUpRoute
|
||||||
'/subscribe': typeof AuthenticatedSubscribeRoute
|
'/subscribe': typeof AuthenticatedSubscribeRoute
|
||||||
@ -190,6 +197,7 @@ export interface FileRoutesByTo {
|
|||||||
'/reset-password': typeof ResetPasswordRoute
|
'/reset-password': typeof ResetPasswordRoute
|
||||||
'/verify-email': typeof VerifyEmailRoute
|
'/verify-email': typeof VerifyEmailRoute
|
||||||
'/billing': typeof AppBillingRoute
|
'/billing': typeof AppBillingRoute
|
||||||
|
'/support': typeof AppSupportRoute
|
||||||
'/sign-in': typeof AuthSignInRoute
|
'/sign-in': typeof AuthSignInRoute
|
||||||
'/sign-up': typeof AuthSignUpRoute
|
'/sign-up': typeof AuthSignUpRoute
|
||||||
'/subscribe': typeof AuthenticatedSubscribeRoute
|
'/subscribe': typeof AuthenticatedSubscribeRoute
|
||||||
@ -215,6 +223,7 @@ export interface FileRoutesById {
|
|||||||
'/reset-password': typeof ResetPasswordRoute
|
'/reset-password': typeof ResetPasswordRoute
|
||||||
'/verify-email': typeof VerifyEmailRoute
|
'/verify-email': typeof VerifyEmailRoute
|
||||||
'/_app/billing': typeof AppBillingRoute
|
'/_app/billing': typeof AppBillingRoute
|
||||||
|
'/_app/support': typeof AppSupportRoute
|
||||||
'/_auth/sign-in': typeof AuthSignInRoute
|
'/_auth/sign-in': typeof AuthSignInRoute
|
||||||
'/_auth/sign-up': typeof AuthSignUpRoute
|
'/_auth/sign-up': typeof AuthSignUpRoute
|
||||||
'/_authenticated/subscribe': typeof AuthenticatedSubscribeRoute
|
'/_authenticated/subscribe': typeof AuthenticatedSubscribeRoute
|
||||||
@ -241,6 +250,7 @@ export interface FileRouteTypes {
|
|||||||
| '/reset-password'
|
| '/reset-password'
|
||||||
| '/verify-email'
|
| '/verify-email'
|
||||||
| '/billing'
|
| '/billing'
|
||||||
|
| '/support'
|
||||||
| '/sign-in'
|
| '/sign-in'
|
||||||
| '/sign-up'
|
| '/sign-up'
|
||||||
| '/subscribe'
|
| '/subscribe'
|
||||||
@ -264,6 +274,7 @@ export interface FileRouteTypes {
|
|||||||
| '/reset-password'
|
| '/reset-password'
|
||||||
| '/verify-email'
|
| '/verify-email'
|
||||||
| '/billing'
|
| '/billing'
|
||||||
|
| '/support'
|
||||||
| '/sign-in'
|
| '/sign-in'
|
||||||
| '/sign-up'
|
| '/sign-up'
|
||||||
| '/subscribe'
|
| '/subscribe'
|
||||||
@ -288,6 +299,7 @@ export interface FileRouteTypes {
|
|||||||
| '/reset-password'
|
| '/reset-password'
|
||||||
| '/verify-email'
|
| '/verify-email'
|
||||||
| '/_app/billing'
|
| '/_app/billing'
|
||||||
|
| '/_app/support'
|
||||||
| '/_auth/sign-in'
|
| '/_auth/sign-in'
|
||||||
| '/_auth/sign-up'
|
| '/_auth/sign-up'
|
||||||
| '/_authenticated/subscribe'
|
| '/_authenticated/subscribe'
|
||||||
@ -398,6 +410,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof AuthSignInRouteImport
|
preLoaderRoute: typeof AuthSignInRouteImport
|
||||||
parentRoute: typeof AuthRoute
|
parentRoute: typeof AuthRoute
|
||||||
}
|
}
|
||||||
|
'/_app/support': {
|
||||||
|
id: '/_app/support'
|
||||||
|
path: '/support'
|
||||||
|
fullPath: '/support'
|
||||||
|
preLoaderRoute: typeof AppSupportRouteImport
|
||||||
|
parentRoute: typeof AppRouteRoute
|
||||||
|
}
|
||||||
'/_app/billing': {
|
'/_app/billing': {
|
||||||
id: '/_app/billing'
|
id: '/_app/billing'
|
||||||
path: '/billing'
|
path: '/billing'
|
||||||
@ -501,12 +520,14 @@ declare module '@tanstack/react-router' {
|
|||||||
|
|
||||||
interface AppRouteRouteChildren {
|
interface AppRouteRouteChildren {
|
||||||
AppBillingRoute: typeof AppBillingRoute
|
AppBillingRoute: typeof AppBillingRoute
|
||||||
|
AppSupportRoute: typeof AppSupportRoute
|
||||||
AppIndexRoute: typeof AppIndexRoute
|
AppIndexRoute: typeof AppIndexRoute
|
||||||
AppHelpDataforseoApiKeyRoute: typeof AppHelpDataforseoApiKeyRoute
|
AppHelpDataforseoApiKeyRoute: typeof AppHelpDataforseoApiKeyRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
const AppRouteRouteChildren: AppRouteRouteChildren = {
|
const AppRouteRouteChildren: AppRouteRouteChildren = {
|
||||||
AppBillingRoute: AppBillingRoute,
|
AppBillingRoute: AppBillingRoute,
|
||||||
|
AppSupportRoute: AppSupportRoute,
|
||||||
AppIndexRoute: AppIndexRoute,
|
AppIndexRoute: AppIndexRoute,
|
||||||
AppHelpDataforseoApiKeyRoute: AppHelpDataforseoApiKeyRoute,
|
AppHelpDataforseoApiKeyRoute: AppHelpDataforseoApiKeyRoute,
|
||||||
}
|
}
|
||||||
|
|||||||
93
src/routes/_app/support.tsx
Normal file
93
src/routes/_app/support.tsx
Normal file
@ -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 (
|
||||||
|
<div className="h-full overflow-auto bg-base-100 px-4 py-8 pb-24 md:px-6 md:py-12 md:pb-8">
|
||||||
|
<div className="mx-auto max-w-xl">
|
||||||
|
<p className="text-sm font-medium text-base-content/40">
|
||||||
|
Help & Community
|
||||||
|
</p>
|
||||||
|
<h1 className="mt-1 text-2xl font-bold tracking-tight">
|
||||||
|
We want to hear from you
|
||||||
|
</h1>
|
||||||
|
<p className="mt-2 text-sm text-base-content/60">
|
||||||
|
We want to talk to you! We're super open to feedback and want to learn
|
||||||
|
how you work so we can make OpenSEO better.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="mt-8 space-y-3">
|
||||||
|
<div className="rounded-lg border border-base-300 px-5 py-4">
|
||||||
|
<p className="text-sm font-semibold">Email</p>
|
||||||
|
<p className="mt-1 text-sm text-base-content/60">
|
||||||
|
Send ideas, problems, questions, or feedback directly.
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleCopy}
|
||||||
|
className="mt-3 inline-flex items-center gap-2 rounded-md border border-base-300 bg-base-200/50 px-3 py-1.5 text-sm font-medium text-base-content transition-colors hover:bg-base-200"
|
||||||
|
>
|
||||||
|
<span className="font-mono text-xs">{SUPPORT_EMAIL}</span>
|
||||||
|
{copied ? (
|
||||||
|
<Check className="size-3.5 text-success" />
|
||||||
|
) : (
|
||||||
|
<Copy className="size-3.5 text-base-content/40" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href={DISCORD_URL}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="block rounded-lg border border-base-300 px-5 py-4 transition-colors hover:border-base-content/20"
|
||||||
|
>
|
||||||
|
<p className="text-sm font-semibold">Discord</p>
|
||||||
|
<p className="mt-1 text-sm text-base-content/60">
|
||||||
|
Ask for help, share ideas and learn from the community.
|
||||||
|
</p>
|
||||||
|
<span className="mt-3 inline-flex items-center gap-1.5 text-sm font-medium text-base-content">
|
||||||
|
Join the Discord
|
||||||
|
<span aria-hidden="true">→</span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href={`${GITHUB_URL}/issues`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="block rounded-lg border border-base-300 px-5 py-4 transition-colors hover:border-base-content/20"
|
||||||
|
>
|
||||||
|
<p className="text-sm font-semibold">GitHub Issues</p>
|
||||||
|
<p className="mt-1 text-sm text-base-content/60">
|
||||||
|
Report bugs or request features on GitHub.
|
||||||
|
</p>
|
||||||
|
<span className="mt-3 inline-flex items-center gap-1.5 text-sm font-medium text-base-content">
|
||||||
|
Open an issue
|
||||||
|
<span aria-hidden="true">→</span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user