chore: server-and-serverless template

This commit is contained in:
e2e
2026-06-26 15:01:11 +02:00
commit a5f832e9ed
202 changed files with 9060 additions and 0 deletions

View File

@@ -0,0 +1,103 @@
import {
AppShell as MantineAppShell,
Box,
Button,
Group,
NavLink,
Stack,
Text,
Title,
} from '@pikku/mantine/core'
import { Link, Outlet } from '@tanstack/react-router'
import { asI18n } from '@pikku/react'
import { useState } from 'react'
import { m } from '@/i18n/messages'
import { useLocale } from '@/i18n/config'
import { usePikkuQuery } from '@project/functions-sdk/pikku/api.gen'
import { signOut } from '@/lib/auth'
import { LanguageSelector } from './LanguageSelector'
import { ThemeSelector } from './ThemeSelector'
export function AppShell() {
useLocale()
const session = usePikkuQuery('getSession', {})
const [isSigningOut, setIsSigningOut] = useState(false)
return (
<MantineAppShell
header={{ height: 88 }}
navbar={{ width: 250, breakpoint: 'sm' }}
padding="lg"
styles={{
main: {
background:
'radial-gradient(circle at top left, rgba(96, 165, 250, 0.12), transparent 26%), linear-gradient(180deg, #10203a 0%, #07111e 56%, #040913 100%)',
},
}}
>
<MantineAppShell.Header px="lg" py="md">
<Group justify="space-between" align="center" h="100%">
<div>
<Text tt="uppercase" fw={700} fz="xs" c="blue.3" style={{ letterSpacing: '0.18em' }}>
{m.app_shell__eyebrow()}
</Text>
<Title order={2}>{m.app_shell__title()}</Title>
</div>
<Group gap="md">
<LanguageSelector />
<ThemeSelector />
<Box
px="md"
py="xs"
style={{
border: '1px solid var(--mantine-color-dark-4)',
borderRadius: '1rem',
background: 'rgba(255,255,255,0.03)',
}}
>
<Text size="xs" c="dimmed">
{session.data?.name ? asI18n(session.data.name) : m.app_shell__signed_in()}
</Text>
<Text fw={600}>
{session.data?.email ? asI18n(session.data.email) : m.common__loading()}
</Text>
</Box>
<Button
variant="light"
radius="md"
loading={isSigningOut}
onClick={async () => {
setIsSigningOut(true)
try {
await signOut()
window.location.href = '/login'
} finally {
setIsSigningOut(false)
}
}}
>
{m.app_shell__sign_out()}
</Button>
</Group>
</Group>
</MantineAppShell.Header>
<MantineAppShell.Navbar p="md">
<Stack gap="xs">
<NavLink
component={Link}
to="/app"
label={m.app_shell__nav__message()}
description={m.app_shell__nav__message_description()}
variant="filled"
activeOptions={{ exact: true }}
/>
</Stack>
</MantineAppShell.Navbar>
<MantineAppShell.Main>
<Outlet />
</MantineAppShell.Main>
</MantineAppShell>
)
}