chore: heygermany customer project
This commit is contained in:
9
apps/website/src/router.tsx
Normal file
9
apps/website/src/router.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import { createRouter } from '@tanstack/react-router'
|
||||
import { routeTree } from './routeTree.gen'
|
||||
|
||||
export function getRouter() {
|
||||
return createRouter({
|
||||
routeTree,
|
||||
scrollRestoration: true,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import BackOfficeLoginPage from '@/views/[lang]/(app)/backoffice/auth/login/page'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_app/backoffice/auth/login')({
|
||||
component: BackOfficeLoginPage,
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import BackOfficeCandidatePage from '@/views/[lang]/(app)/backoffice/candidate/[candidateId]/page'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_app/backoffice/candidate/$candidateId')({
|
||||
component: BackOfficeCandidatePage,
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import BackOfficeCandidatesPage from '@/views/[lang]/(app)/backoffice/candidates/page'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_app/backoffice/candidates')({
|
||||
component: BackOfficeCandidatesPage,
|
||||
})
|
||||
10
apps/website/src/routes/$lang._app.backoffice.dashboard.tsx
Normal file
10
apps/website/src/routes/$lang._app.backoffice.dashboard.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import { createFileRoute, redirect } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_app/backoffice/dashboard')({
|
||||
beforeLoad: ({ params }) => {
|
||||
throw redirect({
|
||||
to: '/$lang/backoffice/candidates',
|
||||
params: { lang: params.lang },
|
||||
})
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import NextStepsHelpPage from '@/views/[lang]/(app)/backoffice/help/nextsteps/page'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_app/backoffice/help/nextsteps')({
|
||||
component: NextStepsHelpPage,
|
||||
})
|
||||
6
apps/website/src/routes/$lang._app.backoffice.index.tsx
Normal file
6
apps/website/src/routes/$lang._app.backoffice.index.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import BackOfficeIndexPage from '@/views/[lang]/(app)/backoffice/page'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_app/backoffice/')({
|
||||
component: BackOfficeIndexPage,
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import BackOfficeTranslationsPage from '@/views/[lang]/(app)/backoffice/translations/page'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_app/backoffice/translations')({
|
||||
component: BackOfficeTranslationsPage,
|
||||
})
|
||||
14
apps/website/src/routes/$lang._app.backoffice.tsx
Normal file
14
apps/website/src/routes/$lang._app.backoffice.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Outlet, createFileRoute } from '@tanstack/react-router'
|
||||
import BackOfficeLayout from '@/views/[lang]/(app)/backoffice/layout'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_app/backoffice')({
|
||||
component: BackOfficeRouteLayout,
|
||||
})
|
||||
|
||||
function BackOfficeRouteLayout() {
|
||||
return (
|
||||
<BackOfficeLayout>
|
||||
<Outlet />
|
||||
</BackOfficeLayout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import CompanyLoginPage from '@/views/[lang]/(app)/company/auth/login/page'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_app/company/auth/login')({
|
||||
component: CompanyLoginPage,
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import CompanyCandidatePage from '@/views/[lang]/(app)/company/candidate/[candidateId]/page'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_app/company/candidate/$candidateId')({
|
||||
component: CompanyCandidatePage,
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import CompanyCandidatesPage from '@/views/[lang]/(app)/company/candidates/page'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_app/company/candidates')({
|
||||
component: CompanyCandidatesPage,
|
||||
})
|
||||
6
apps/website/src/routes/$lang._app.company.index.tsx
Normal file
6
apps/website/src/routes/$lang._app.company.index.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import CompanyPage from '@/views/[lang]/(app)/company/page'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_app/company/')({
|
||||
component: CompanyPage,
|
||||
})
|
||||
14
apps/website/src/routes/$lang._app.company.tsx
Normal file
14
apps/website/src/routes/$lang._app.company.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Outlet, createFileRoute } from '@tanstack/react-router'
|
||||
import CompanyLayout from '@/views/[lang]/(app)/company/layout'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_app/company')({
|
||||
component: CompanyRouteLayout,
|
||||
})
|
||||
|
||||
function CompanyRouteLayout() {
|
||||
return (
|
||||
<CompanyLayout>
|
||||
<Outlet />
|
||||
</CompanyLayout>
|
||||
)
|
||||
}
|
||||
6
apps/website/src/routes/$lang._app.logout.tsx
Normal file
6
apps/website/src/routes/$lang._app.logout.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import LogoutPage from '@/views/[lang]/(app)/logout/page'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_app/logout')({
|
||||
component: LogoutPage,
|
||||
})
|
||||
8
apps/website/src/routes/$lang._app.tsx
Normal file
8
apps/website/src/routes/$lang._app.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Outlet, createFileRoute } from '@tanstack/react-router'
|
||||
import { NO_INDEX_METADATA } from '@/lib/seo'
|
||||
import { metadataToHead } from '@/framework/head'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_app')({
|
||||
head: () => metadataToHead(NO_INDEX_METADATA),
|
||||
component: Outlet,
|
||||
})
|
||||
17
apps/website/src/routes/$lang._main.about.tsx
Normal file
17
apps/website/src/routes/$lang._main.about.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import AboutPage from '@/views/[lang]/(main)/about/page'
|
||||
import { createPageMetadata, getMessage } from '@/lib/seo'
|
||||
import { metadataToHead } from '@/framework/head'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_main/about')({
|
||||
head: ({ params }) =>
|
||||
metadataToHead(
|
||||
createPageMetadata({
|
||||
locale: params.lang,
|
||||
pathname: '/about',
|
||||
title: getMessage(params.lang, 'website.about.title'),
|
||||
description: getMessage(params.lang, 'website.about.description'),
|
||||
})
|
||||
),
|
||||
component: AboutPage,
|
||||
})
|
||||
9
apps/website/src/routes/$lang._main.auth.magic-link.tsx
Normal file
9
apps/website/src/routes/$lang._main.auth.magic-link.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import MagicLinkPage from '@/views/[lang]/(main)/auth/magic-link/page'
|
||||
import { NO_INDEX_METADATA } from '@/lib/seo'
|
||||
import { metadataToHead } from '@/framework/head'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_main/auth/magic-link')({
|
||||
head: () => metadataToHead(NO_INDEX_METADATA),
|
||||
component: MagicLinkPage,
|
||||
})
|
||||
9
apps/website/src/routes/$lang._main.jobs.application.tsx
Normal file
9
apps/website/src/routes/$lang._main.jobs.application.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import ApplicationPage from '@/views/[lang]/(main)/jobs/application/page'
|
||||
import { NO_INDEX_METADATA } from '@/lib/seo'
|
||||
import { metadataToHead } from '@/framework/head'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_main/jobs/application')({
|
||||
head: () => metadataToHead(NO_INDEX_METADATA),
|
||||
component: ApplicationPage,
|
||||
})
|
||||
17
apps/website/src/routes/$lang._main.jobs.apply.tsx
Normal file
17
apps/website/src/routes/$lang._main.jobs.apply.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import ApplyPage from '@/views/[lang]/(main)/jobs/apply/page'
|
||||
import { createPageMetadata, getMessage } from '@/lib/seo'
|
||||
import { metadataToHead } from '@/framework/head'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_main/jobs/apply')({
|
||||
head: ({ params }) =>
|
||||
metadataToHead(
|
||||
createPageMetadata({
|
||||
locale: params.lang,
|
||||
pathname: '/jobs/apply',
|
||||
title: getMessage(params.lang, 'website.hero.cta'),
|
||||
description: getMessage(params.lang, 'jobs.apply.getyourresults.description'),
|
||||
})
|
||||
),
|
||||
component: ApplyPage,
|
||||
})
|
||||
15
apps/website/src/routes/$lang._main.jobs.result.demo.tsx
Normal file
15
apps/website/src/routes/$lang._main.jobs.result.demo.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import DemoResultPage from '@/views/[lang]/(main)/jobs/result/demo/page'
|
||||
import { metadataToHead } from '@/framework/head'
|
||||
import { NO_INDEX_METADATA } from '@/lib/seo'
|
||||
|
||||
const demoResultMetadata = {
|
||||
title: 'Qualification Result | HeyGermany',
|
||||
description: 'Candidate qualification result page.',
|
||||
...NO_INDEX_METADATA,
|
||||
}
|
||||
|
||||
export const Route = createFileRoute('/$lang/_main/jobs/result/demo')({
|
||||
head: () => metadataToHead(demoResultMetadata),
|
||||
component: DemoResultPage,
|
||||
})
|
||||
17
apps/website/src/routes/$lang._main.jobs.result.tsx
Normal file
17
apps/website/src/routes/$lang._main.jobs.result.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import { createFileRoute, redirect } from '@tanstack/react-router'
|
||||
import { NO_INDEX_METADATA } from '@/lib/seo'
|
||||
import { metadataToHead } from '@/framework/head'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_main/jobs/result')({
|
||||
head: () => metadataToHead(NO_INDEX_METADATA),
|
||||
beforeLoad: ({ params, location }) => {
|
||||
if (location.pathname === `/${params.lang}/jobs/result/demo`) {
|
||||
return
|
||||
}
|
||||
|
||||
throw redirect({
|
||||
to: '/$lang/jobs/apply',
|
||||
params: { lang: params.lang },
|
||||
})
|
||||
},
|
||||
})
|
||||
14
apps/website/src/routes/$lang._main.tsx
Normal file
14
apps/website/src/routes/$lang._main.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Outlet, createFileRoute } from '@tanstack/react-router'
|
||||
import MainLayout from '@/views/[lang]/(main)/layout'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_main')({
|
||||
component: MainRouteLayout,
|
||||
})
|
||||
|
||||
function MainRouteLayout() {
|
||||
return (
|
||||
<MainLayout>
|
||||
<Outlet />
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
9
apps/website/src/routes/$lang._main.verify-email.tsx
Normal file
9
apps/website/src/routes/$lang._main.verify-email.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import VerifyEmailPage from '@/views/[lang]/(main)/verify-email/page'
|
||||
import { NO_INDEX_METADATA } from '@/lib/seo'
|
||||
import { metadataToHead } from '@/framework/head'
|
||||
|
||||
export const Route = createFileRoute('/$lang/_main/verify-email')({
|
||||
head: () => metadataToHead(NO_INDEX_METADATA),
|
||||
component: VerifyEmailPage,
|
||||
})
|
||||
9
apps/website/src/routes/$lang.index.tsx
Normal file
9
apps/website/src/routes/$lang.index.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import LocalizedHomePage from '@/views/[lang]/(main)/page'
|
||||
import { createHomepageMetadata } from '@/lib/seo'
|
||||
import { metadataToHead } from '@/framework/head'
|
||||
|
||||
export const Route = createFileRoute('/$lang/')({
|
||||
head: ({ params }) => metadataToHead(createHomepageMetadata(params.lang)),
|
||||
component: LocalizedHomePage,
|
||||
})
|
||||
21
apps/website/src/routes/$lang.legal.imprint.tsx
Normal file
21
apps/website/src/routes/$lang.legal.imprint.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import ImprintPage from '@/views/[lang]/legal/imprint/page'
|
||||
import { DEFAULT_LOCALE } from '@/config'
|
||||
import { createPageMetadata } from '@/lib/seo'
|
||||
import { metadataToHead } from '@/framework/head'
|
||||
|
||||
export const Route = createFileRoute('/$lang/legal/imprint')({
|
||||
head: ({ params }) =>
|
||||
metadataToHead(
|
||||
createPageMetadata({
|
||||
locale: params.lang,
|
||||
canonicalLocale: DEFAULT_LOCALE,
|
||||
availableLocales: [DEFAULT_LOCALE],
|
||||
pathname: '/legal/imprint',
|
||||
title: 'Imprint',
|
||||
description: 'Legal notice and company information for HeyGermany.',
|
||||
index: params.lang === DEFAULT_LOCALE,
|
||||
})
|
||||
),
|
||||
component: ImprintPage,
|
||||
})
|
||||
21
apps/website/src/routes/$lang.legal.privacy.tsx
Normal file
21
apps/website/src/routes/$lang.legal.privacy.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import PrivacyPage from '@/views/[lang]/legal/privacy/page'
|
||||
import { DEFAULT_LOCALE } from '@/config'
|
||||
import { createPageMetadata } from '@/lib/seo'
|
||||
import { metadataToHead } from '@/framework/head'
|
||||
|
||||
export const Route = createFileRoute('/$lang/legal/privacy')({
|
||||
head: ({ params }) =>
|
||||
metadataToHead(
|
||||
createPageMetadata({
|
||||
locale: params.lang,
|
||||
canonicalLocale: DEFAULT_LOCALE,
|
||||
availableLocales: [DEFAULT_LOCALE],
|
||||
pathname: '/legal/privacy',
|
||||
title: 'Privacy Policy',
|
||||
description: 'How HeyGermany collects, uses, and protects personal data.',
|
||||
index: params.lang === DEFAULT_LOCALE,
|
||||
})
|
||||
),
|
||||
component: PrivacyPage,
|
||||
})
|
||||
21
apps/website/src/routes/$lang.legal.terms-and-conditions.tsx
Normal file
21
apps/website/src/routes/$lang.legal.terms-and-conditions.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import TermsPage from '@/views/[lang]/legal/terms-and-conditions/page'
|
||||
import { DEFAULT_LOCALE } from '@/config'
|
||||
import { createPageMetadata } from '@/lib/seo'
|
||||
import { metadataToHead } from '@/framework/head'
|
||||
|
||||
export const Route = createFileRoute('/$lang/legal/terms-and-conditions')({
|
||||
head: ({ params }) =>
|
||||
metadataToHead(
|
||||
createPageMetadata({
|
||||
locale: params.lang,
|
||||
canonicalLocale: DEFAULT_LOCALE,
|
||||
availableLocales: [DEFAULT_LOCALE],
|
||||
pathname: '/legal/terms-and-conditions',
|
||||
title: 'Terms and Conditions',
|
||||
description: 'Terms and conditions for using the HeyGermany platform and services.',
|
||||
index: params.lang === DEFAULT_LOCALE,
|
||||
})
|
||||
),
|
||||
component: TermsPage,
|
||||
})
|
||||
14
apps/website/src/routes/$lang.legal.tsx
Normal file
14
apps/website/src/routes/$lang.legal.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Outlet, createFileRoute } from '@tanstack/react-router'
|
||||
import LegalLayout from '@/views/[lang]/legal/layout'
|
||||
|
||||
export const Route = createFileRoute('/$lang/legal')({
|
||||
component: LegalRouteLayout,
|
||||
})
|
||||
|
||||
function LegalRouteLayout() {
|
||||
return (
|
||||
<LegalLayout>
|
||||
<Outlet />
|
||||
</LegalLayout>
|
||||
)
|
||||
}
|
||||
31
apps/website/src/routes/$lang.tsx
Normal file
31
apps/website/src/routes/$lang.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import { Outlet, createFileRoute, useLocation } from '@tanstack/react-router'
|
||||
import { LocalizedLayout } from '@/framework/localized-layout'
|
||||
import { normalizeLocale } from '@/lib/seo'
|
||||
import LocalizedHomePage from '@/views/[lang]/(main)/page'
|
||||
import { NotFoundTitle } from '@/components/NotFoundTitle'
|
||||
|
||||
export const Route = createFileRoute('/$lang')({
|
||||
component: LangRoute,
|
||||
notFoundComponent: LangNotFound,
|
||||
})
|
||||
|
||||
function LangRoute() {
|
||||
const { lang } = Route.useParams()
|
||||
|
||||
return (
|
||||
<LocalizedLayout lang={normalizeLocale(lang)}>
|
||||
<Outlet />
|
||||
</LocalizedLayout>
|
||||
)
|
||||
}
|
||||
|
||||
function LangNotFound() {
|
||||
const { lang } = Route.useParams()
|
||||
const pathname = useLocation({ select: (location) => location.pathname })
|
||||
|
||||
if (pathname === `/${lang}`) {
|
||||
return <LocalizedHomePage />
|
||||
}
|
||||
|
||||
return <NotFoundTitle />
|
||||
}
|
||||
74
apps/website/src/routes/__root.tsx
Normal file
74
apps/website/src/routes/__root.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
import { HeadContent, Outlet, Scripts, createRootRoute, useLocation } from '@tanstack/react-router'
|
||||
import { RootDocument } from '@/framework/root-document'
|
||||
import { NotFoundTitle } from '@/components/NotFoundTitle'
|
||||
import { metadataToHead } from '@/framework/head'
|
||||
import {
|
||||
DEFAULT_OG_IMAGE,
|
||||
DEFAULT_SITE_DESCRIPTION,
|
||||
DEFAULT_SITE_TITLE,
|
||||
SITE_NAME,
|
||||
SITE_URL,
|
||||
getAbsoluteUrl,
|
||||
} from '@/lib/seo'
|
||||
import { getResolvedLocale } from '@/lib/request-routing'
|
||||
|
||||
const rootMetadata = {
|
||||
metadataBase: new URL(SITE_URL),
|
||||
applicationName: SITE_NAME,
|
||||
title: DEFAULT_SITE_TITLE,
|
||||
description: DEFAULT_SITE_DESCRIPTION,
|
||||
manifest: '/site.webmanifest',
|
||||
icons: {
|
||||
icon: [
|
||||
{ url: '/favicon.ico' },
|
||||
{ url: '/favicon-16x16.png', sizes: '16x16', type: 'image/png' },
|
||||
{ url: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' },
|
||||
],
|
||||
apple: [{ url: '/apple-touch-icon.png', sizes: '180x180' }],
|
||||
},
|
||||
openGraph: {
|
||||
title: DEFAULT_SITE_TITLE,
|
||||
description: DEFAULT_SITE_DESCRIPTION,
|
||||
url: SITE_URL,
|
||||
siteName: SITE_NAME,
|
||||
type: 'website',
|
||||
images: [{ url: getAbsoluteUrl(DEFAULT_OG_IMAGE), alt: SITE_NAME }],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: DEFAULT_SITE_TITLE,
|
||||
description: DEFAULT_SITE_DESCRIPTION,
|
||||
images: [getAbsoluteUrl(DEFAULT_OG_IMAGE)],
|
||||
},
|
||||
}
|
||||
|
||||
export const Route = createRootRoute({
|
||||
head: () => metadataToHead(rootMetadata),
|
||||
notFoundComponent: NotFoundTitle,
|
||||
component: RootComponent,
|
||||
})
|
||||
|
||||
function RootComponent() {
|
||||
const pathname = useLocation({ select: (location) => location.pathname })
|
||||
const lang = getResolvedLocale(pathname)
|
||||
const initialTheme =
|
||||
typeof document === 'undefined'
|
||||
? 'light'
|
||||
: ((document.cookie
|
||||
.split(';')
|
||||
.map((part) => part.trim())
|
||||
.find((part) => part.startsWith('mantine-color-scheme='))
|
||||
?.split('=')[1] ?? 'light') as 'light' | 'dark' | 'auto')
|
||||
|
||||
return (
|
||||
<RootDocument
|
||||
lang={lang}
|
||||
initialTheme={initialTheme}
|
||||
gaId={import.meta.env.VITE_GA_ID ?? import.meta.env.GA_ID}
|
||||
headContent={<HeadContent />}
|
||||
bodyEnd={<Scripts />}
|
||||
>
|
||||
<Outlet />
|
||||
</RootDocument>
|
||||
)
|
||||
}
|
||||
35
apps/website/src/routes/api.auth.$.ts
Normal file
35
apps/website/src/routes/api.auth.$.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
const getApiOrigin = () => {
|
||||
return process.env.VITE_API_BASE_URL || process.env.API_URL || 'http://localhost:3000'
|
||||
}
|
||||
|
||||
const proxyAuthRequest = async (request: Request, splat: string | undefined) => {
|
||||
const target = new URL(`/api/auth/${splat || ''}`, getApiOrigin())
|
||||
|
||||
if (request.url.includes('?')) {
|
||||
target.search = new URL(request.url).search
|
||||
}
|
||||
|
||||
const upstream = await fetch(target, {
|
||||
method: request.method,
|
||||
headers: request.headers,
|
||||
body: request.method === 'GET' || request.method === 'HEAD' ? undefined : await request.blob(),
|
||||
redirect: 'manual',
|
||||
})
|
||||
|
||||
return new Response(upstream.body, {
|
||||
status: upstream.status,
|
||||
statusText: upstream.statusText,
|
||||
headers: upstream.headers,
|
||||
})
|
||||
}
|
||||
|
||||
export const Route = createFileRoute('/api/auth/$')({
|
||||
server: {
|
||||
handlers: {
|
||||
GET: async ({ request, params }) => proxyAuthRequest(request, params._splat),
|
||||
POST: async ({ request, params }) => proxyAuthRequest(request, params._splat),
|
||||
},
|
||||
},
|
||||
})
|
||||
10
apps/website/src/routes/api.health.ts
Normal file
10
apps/website/src/routes/api.health.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { getHealthResponse } from '@/lib/health'
|
||||
|
||||
export const Route = createFileRoute('/api/health')({
|
||||
server: {
|
||||
handlers: {
|
||||
GET: async () => getHealthResponse(),
|
||||
},
|
||||
},
|
||||
})
|
||||
39
apps/website/src/routes/pilot.tsx
Normal file
39
apps/website/src/routes/pilot.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import PilotPage from '@/views/pilot/page'
|
||||
import { metadataToHead } from '@/framework/head'
|
||||
import { DEFAULT_OG_IMAGE, SITE_NAME, getAbsoluteUrl } from '@/lib/seo'
|
||||
|
||||
const pilotMetadata = {
|
||||
title: 'Pilot-Partner werden | HeyGermany',
|
||||
description:
|
||||
'HeyGermany sucht Pilot-Partner unter deutschen Pflegeeinrichtungen, die internationale Pflegefachkraefte ohne klassische Agenturmodelle gewinnen wollen.',
|
||||
alternates: {
|
||||
canonical: 'https://hey-germany.com/pilot',
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Pilot-Partner werden | HeyGermany',
|
||||
description:
|
||||
'Vorqualifizierte internationale Pflegefachkraefte, Full-Service Recruiting und der Aufbau eigener Prozesse fuer nachhaltige Rekrutierung.',
|
||||
url: 'https://hey-germany.com/pilot',
|
||||
siteName: SITE_NAME,
|
||||
type: 'website',
|
||||
images: [
|
||||
{
|
||||
url: getAbsoluteUrl(DEFAULT_OG_IMAGE),
|
||||
alt: 'Pilot-Partner werden | HeyGermany',
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Pilot-Partner werden | HeyGermany',
|
||||
description:
|
||||
'Vorqualifizierte internationale Pflegefachkraefte, Full-Service Recruiting und der Aufbau eigener Prozesse fuer nachhaltige Rekrutierung.',
|
||||
images: [getAbsoluteUrl(DEFAULT_OG_IMAGE)],
|
||||
},
|
||||
}
|
||||
|
||||
export const Route = createFileRoute('/pilot')({
|
||||
head: () => metadataToHead(pilotMetadata),
|
||||
component: PilotPage,
|
||||
})
|
||||
29
apps/website/src/routes/robots[.]txt.ts
Normal file
29
apps/website/src/routes/robots[.]txt.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { getRobotsConfig } from '@/lib/robots'
|
||||
|
||||
function renderRobotsTxt() {
|
||||
const robots = getRobotsConfig()
|
||||
const lines = robots.rules.flatMap((rule) => [
|
||||
`User-agent: ${rule.userAgent}`,
|
||||
`Allow: ${rule.allow}`,
|
||||
...(rule.disallow ?? []).map((path) => `Disallow: ${path}`),
|
||||
])
|
||||
|
||||
lines.push(`Sitemap: ${robots.sitemap}`)
|
||||
lines.push(`Host: ${robots.host}`)
|
||||
|
||||
return `${lines.join('\n')}\n`
|
||||
}
|
||||
|
||||
export const Route = createFileRoute('/robots.txt')({
|
||||
server: {
|
||||
handlers: {
|
||||
GET: async () =>
|
||||
new Response(renderRobotsTxt(), {
|
||||
headers: {
|
||||
'content-type': 'text/plain; charset=utf-8',
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
})
|
||||
44
apps/website/src/start.ts
Normal file
44
apps/website/src/start.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import '@mantine/core/styles.css'
|
||||
import '@mantine/dates/styles.css'
|
||||
import 'mantine-datatable/styles.layer.css'
|
||||
import '@/views/[lang]/globals.css'
|
||||
|
||||
import { createMiddleware, createStart } from '@tanstack/react-start'
|
||||
import { redirect } from '@tanstack/react-router'
|
||||
import { resolveRequestRouting } from '@/lib/request-routing'
|
||||
|
||||
export const startInstance = createStart(() => ({
|
||||
requestMiddleware: [
|
||||
createStartRequestMiddleware(),
|
||||
],
|
||||
}))
|
||||
|
||||
function createStartRequestMiddleware() {
|
||||
return createMiddleware().server(async ({ request, next }) => {
|
||||
const result = await resolveRequestRouting({
|
||||
url: request.url,
|
||||
pathname: new URL(request.url).pathname,
|
||||
search: new URL(request.url).search,
|
||||
headers: request.headers,
|
||||
cookies: new Map(
|
||||
(request.headers.get('cookie') ?? '')
|
||||
.split(';')
|
||||
.map((part) => part.trim())
|
||||
.filter(Boolean)
|
||||
.map((part) => {
|
||||
const index = part.indexOf('=')
|
||||
return [
|
||||
part.slice(0, index),
|
||||
decodeURIComponent(part.slice(index + 1)),
|
||||
] as const
|
||||
})
|
||||
),
|
||||
})
|
||||
|
||||
if (result.type === 'redirect') {
|
||||
throw redirect({ href: result.location })
|
||||
}
|
||||
|
||||
return next()
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user