Bulk commit

This commit is contained in:
2025-08-21 19:35:07 +02:00
parent 7e35a04cfe
commit 5446120d96
33 changed files with 869 additions and 154 deletions

View File

@ -0,0 +1,110 @@
'use client'
import { BadgeCheck, Bell, ChevronsUpDown, LogOut } from 'lucide-react'
import { Link } from '@tanstack/react-router'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import {
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
useSidebar,
} from '@/components/ui/sidebar'
export function NavUser({
user,
}: {
user: {
name: string
email: string
avatar: string
}
}) {
const { isMobile } = useSidebar()
return (
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuButton
size="lg"
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
>
<Avatar className="h-8 w-8 rounded-lg">
<AvatarImage src={user.avatar} alt={user.name} />
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
</Avatar>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-medium">{user.name}</span>
<span className="truncate text-xs">{user.email}</span>
</div>
<ChevronsUpDown className="ml-auto size-4" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
className="w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg"
side={isMobile ? 'bottom' : 'right'}
align="end"
sideOffset={4}
>
<DropdownMenuLabel className="p-0 font-normal">
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
<Avatar className="h-8 w-8 rounded-lg">
<AvatarImage src={user.avatar} alt={user.name} />
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
</Avatar>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-medium">{user.name}</span>
<span className="truncate text-xs">{user.email}</span>
</div>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
{/* <DropdownMenuGroup>
<DropdownMenuItem>
<Sparkles />
Upgrade to Pro
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator /> */}
<DropdownMenuGroup>
<Link to="/about">
<DropdownMenuItem>
<BadgeCheck />
Account
</DropdownMenuItem>
</Link>
{/* <DropdownMenuItem>
<CreditCard />
Billing
</DropdownMenuItem> */}
<Link to="/">
<DropdownMenuItem>
<Bell />
Notifications
</DropdownMenuItem>
</Link>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<a href="http://localhost:3000/api/logout">
<DropdownMenuItem>
<LogOut />
Log out
</DropdownMenuItem>
</a>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
)
}

View File

@ -0,0 +1,14 @@
import { useCurrentSession } from '../queries'
function Session() {
const { data: session } = useCurrentSession()
return (
<div>
Session
{JSON.stringify(session)}
</div>
)
}
export default Session

View File

@ -0,0 +1,27 @@
import { useQuery } from '@tanstack/react-query'
const sessionKeys = {
all: ['sessions'] as const,
current: () => [...sessionKeys.all, 'current'] as const,
}
export type Session = {
Token: string
UserID: number
CreatedAt: Date
}
export function useCurrentSession() {
return useQuery<Session>({
queryKey: sessionKeys.current(),
queryFn: async () => {
const data = await fetch(
'http://localhost:3000/api/auth/currentSession',
{
credentials: 'include',
},
)
return await data.json()
},
})
}

View File

@ -1,10 +1,72 @@
import { Button } from '@/components/ui/button'
import { useAnsprechpartner } from '../queries'
import {
Ansprechpartner,
useAnsprechpartner,
useAnsprechpartnerEditMutation,
} from '../queries'
import { useAppForm } from '@/hooks/demo.form'
function AnsprechpartnerDetail({ id }: { id: number }) {
const { data: ansprechpartner } = useAnsprechpartner(id)
const editAnsprechpartnerMutation = useAnsprechpartnerEditMutation()
return <div></div>
const defaultValues: Ansprechpartner = {
ID: ansprechpartner.ID ?? -1,
CreatedAt: ansprechpartner.CreatedAt ?? new Date(0),
UpdatedAt: ansprechpartner.UpdatedAt ?? new Date(0),
DeletedAt: ansprechpartner.DeletedAt ?? new Date(0),
active: ansprechpartner.active ?? false,
image_url: ansprechpartner.image_url ?? '',
title: ansprechpartner.title ?? '',
first_name: ansprechpartner.first_name ?? '',
last_name: ansprechpartner.last_name ?? '',
last_title: ansprechpartner.last_title ?? '',
e_mail: ansprechpartner.e_mail ?? '',
phone: ansprechpartner.phone ?? '',
mobile: ansprechpartner.mobile ?? '',
description: ansprechpartner.description ?? '',
notes: ansprechpartner.notes ?? '',
gender: ansprechpartner.gender ?? -1,
}
const form = useAppForm({
defaultValues,
onSubmit: ({ value: ap }) => {
editAnsprechpartnerMutation.mutate(ap)
},
})
return (
<div>
<form
onSubmit={(e) => {
e.preventDefault()
e.stopPropagation()
form.handleSubmit()
}}
>
<form.AppField
name="title"
children={(field) => <field.TextField label="Title: " />}
/>
<form.AppField
name="first_name"
children={(field) => <field.TextField label="First Name" />}
/>
<form.AppField
name="last_name"
children={(field) => <field.TextField label="Last Name" />}
/>
<form.AppField
name="last_title"
children={(field) => <field.TextField label="Last Title" />}
/>
<form.AppForm>
<form.SubscribeButton label="Speichern" />
</form.AppForm>
</form>
</div>
)
}
export default AnsprechpartnerDetail

View File

@ -35,7 +35,9 @@ export function useAllAnsprechpartners() {
return useQuery<Ansprechpartner>({
queryKey: ansprechpartnerKeys.lists(),
queryFn: async () => {
const data = await fetch('http://localhost:3000/v1/ansprechpartner/all')
const data = await fetch('http://localhost:3000/v1/ansprechpartner/all', {
credentials: 'include',
})
return await data.json()
},
})
@ -45,7 +47,10 @@ export function useAnsprechpartner(id: number) {
return useSuspenseQuery<Ansprechpartner>({
queryKey: ansprechpartnerKeys.detail(id),
queryFn: async () => {
const data = await fetch('http://localhost:3000/v1/ansprechpartner/' + id)
const data = await fetch(
'http://localhost:3000/v1/ansprechpartner/' + id,
{ credentials: 'include' },
)
return await data.json()
},
})
@ -56,7 +61,7 @@ export function useAnsprechpartnerEditMutation() {
return useMutation({
mutationFn: async (ansprechpartner: Ansprechpartner) => {
const res = await fetch(
await fetch(
'http://localhost:3000/v1/ansprechpartner/' + ansprechpartner.ID,
{
headers: {
@ -64,9 +69,12 @@ export function useAnsprechpartnerEditMutation() {
},
method: 'PUT',
body: JSON.stringify(ansprechpartner),
credentials: 'include',
},
)
console.log('Invalidating queries.')
queryClient.invalidateQueries({
queryKey: [
ansprechpartnerKeys.detail(ansprechpartner.ID),

View File

@ -37,9 +37,10 @@ export function TeamSwitcher() {
if (mandanten && currentMandant) {
const mandant = mandanten[numKey]
if (mandant.id === currentMandant.id) {
if (mandant.ID === currentMandant.ID) {
return
}
console.log(mandant, currentMandant)
editCurrentTeamMutation.mutate(mandanten[numKey])
}
@ -83,7 +84,13 @@ export function TeamSwitcher() {
Teams
</DropdownMenuLabel>
{mandanten.map((mandant, index) => {
return <MandantDMI mandant={mandant} index={index} />
return (
<MandantDMI
mandant={mandant}
currentMandant={currentMandant}
index={index}
/>
)
})}
<DropdownMenuSeparator />
<DropdownMenuItem className="gap-2 p-2">
@ -99,17 +106,22 @@ export function TeamSwitcher() {
)
}
function MandantDMI({ mandant, index }: { mandant: Mandant; index: number }) {
const { data: currentMandant } = useCurrentMandant()
function MandantDMI({
mandant,
currentMandant,
index,
}: {
mandant: Mandant
currentMandant: Mandant
index: number
}) {
const editCurrentMandantMutaiton = useCurrentMandantMutation()
if (!currentMandant) return <p>Loading...</p>
return (
<DropdownMenuItem
key={mandant.name}
key={mandant.ID}
onClick={() => editCurrentMandantMutaiton.mutate(mandant)}
disabled={mandant.id === currentMandant.id}
disabled={mandant.ID === currentMandant.ID}
className="gap-2 p-2"
>
<div

View File

@ -7,7 +7,7 @@ const mandantKeys = {
}
export type Mandant = {
id: string
ID: string
name: string
logo: string
plan: string
@ -18,7 +18,9 @@ export function useCurrentMandant() {
return useQuery<Mandant>({
queryKey: mandantKeys.current(),
queryFn: async () => {
const data = await fetch('http://localhost:3000/v1/mandant/current')
const data = await fetch('http://localhost:3000/v1/mandant/current', {
credentials: 'include',
})
return await data.json()
},
})
@ -28,7 +30,9 @@ export function useAllMandanten() {
return useQuery<Array<Mandant>>({
queryKey: mandantKeys.lists(),
queryFn: async () => {
const data = await fetch('http://localhost:3000/v1/mandant/all')
const data = await fetch('http://localhost:3000/v1/mandant/all', {
credentials: 'include',
})
return await data.json()
},
})
@ -45,6 +49,7 @@ export function useCurrentMandantMutation() {
},
method: 'PUT',
body: JSON.stringify(mandant),
credentials: 'include',
})
const newCurrentMandant = await res.json()
queryClient.setQueryData(