Bulk commit
This commit is contained in:
110
src/features/Auth/components/nav-user.tsx
Normal file
110
src/features/Auth/components/nav-user.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
14
src/features/Auth/components/session.tsx
Normal file
14
src/features/Auth/components/session.tsx
Normal 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
|
||||
27
src/features/Auth/queries.ts
Normal file
27
src/features/Auth/queries.ts
Normal 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()
|
||||
},
|
||||
})
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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(
|
||||
|
||||
Reference in New Issue
Block a user